Calendar/CalendarPopup/CalendarView 日历
注:
- 这 3 个组件是渐进式组件,可查看 渐进式组件 了解。
Import
js
import { TaCalendar, TaCalendarPopup, TaCalendarView } from 'tantalum-ui-mobile'
具体的引入方式可以参考引入组件。
Import Type
组件导出的类型定义:
ts
import type {
CalendarValueFormatter,
CalendarValueParser,
CalendarOnSelect,
CalendarOnConfirm,
CalendarDayHandler,
CalendarMode,
CalendarDetail,
SelectorOnChange,
SelectorModelValue,
VisibleState,
PopupOnVisibleStateChange,
PopupOnCancel
} from 'tantalum-ui-mobile'
公共 Props
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| v-model | SelectorModelValue | [] | 否 | 选中值 |
| min-date | Date | 当前日期 | 否 | 可选最小值 |
| max-date | Date | 当前日期的六个月后 | 否 | 可选最大值 |
| initial-mode | CalendarMode | 'single' | 否 | 模式 |
| allow-same-day | boolean | false | 否 | range 模式生效,设置开始结束时间是否可以同一天 |
| max-range | number | string | Infinity | 否 | range 模式生效,选择区间的最长天数 |
| day-handler | CalendarDayHandler | 否 | 日历每个日期处理函数 | |
| formatter | CalendarValueFormatter | 否 | 和 parser 成对设置,对于 v-model 和 change 的值进行转化 | |
| parser | CalendarValueParser | 否 | 和 formatter 成对设置,对于 v-model 和 change 的值进行反转化 |
Calendar 日历选择器
注:
- 支持表单,具体可参考 Form。
vue
<script setup lang="ts">
import { ref } from 'vue'
import dayjs from 'dayjs'
import { showToast, showCalendar, type SelectorModelValue } from '@/index'
import { formatter, parser, template } from '../Calendar/utils'
const simpleValue = ref([new Date()])
const rangeValue = ref([])
const formatValue = ref(dayjs().format(template))
const minDate = dayjs().startOf('day').subtract(1, 'month').toDate()
const maxDate = dayjs().startOf('day').add(1, 'month').toDate()
function onCallApi() {
showCalendar({
mode: 'range',
showClose: true,
success: res => {
console.log('success', res)
if (res.cancel) {
showToast('取消了')
} else {
showToast(`选择了 ${res.detail.label}`)
}
}
})
}
function onChange(res: SelectorModelValue) {
console.log('change', res)
showToast('change: ' + (res as any)[0])
}
</script>
<script lang="ts">
export default {
name: 'ExpCalendar'
}
</script>
<template>
<ta-group title="initialMode=simple">
<ta-cell label="默认">
<ta-calendar v-model="simpleValue" />
</ta-cell>
<ta-cell label="showConfirm=true">
<ta-calendar showConfirm />
</ta-cell>
<ta-cell label="showClose=true">
<ta-calendar showClose />
</ta-cell>
<ta-cell label="firstDayOfWeek=1">
<ta-calendar :firstDayOfWeek="1" />
</ta-cell>
<ta-cell label="minDate/maxDate +-1month">
<ta-calendar :minDate="minDate" :maxDate="maxDate" />
</ta-cell>
<ta-cell label="formatter/parser">
<ta-calendar
:formatter="formatter"
:parser="parser"
v-model="formatValue"
@change="onChange"
/>
</ta-cell>
<ta-cell label="禁用">
<ta-calendar v-model="simpleValue" disabled />
</ta-cell>
</ta-group>
<ta-group title="initialMode=range">
<ta-cell label="默认">
<ta-calendar initialMode="range" v-model="rangeValue" />
</ta-cell>
<ta-cell label="allowSameDay">
<ta-calendar initialMode="range" allowSameDay />
</ta-cell>
<ta-cell label="maxRange=5">
<ta-calendar initialMode="range" :maxRange="5" />
</ta-cell>
</ta-group>
<ta-group title="事件监听">
<ta-cell label="change">
<ta-calendar @change="onChange" />
</ta-cell>
</ta-group>
<ta-group title="API">
<ta-cell label="showCalendar" isLink @click="onCallApi()" />
</ta-group>
</template>
Calendar Props
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| name | string | 否 | 标识 | |
| placeholder | string | 否 | 没有选中值的提示,也会用在弹窗标题上 | |
| disabled | boolean | false | 否 | 是否禁用 |
| show-confirm | boolean | false | 否 | 弹窗是否展示确定按钮 |
| show-close | boolean | false | 否 | 弹窗是否展示关闭按钮 |
Calendar Events
| 事件 | 描述 | 回调函数参数 | 函数 TypeScript |
|---|---|---|---|
| change | 选择后值发生改变时触发 | payload: SelectorModelValue | SelectorOnChange |
CalendarPopup 日历选择弹窗
vue
<script setup lang="ts">
import { ref } from 'vue'
import dayjs from 'dayjs'
import {
showToast,
type CalendarOnConfirm,
type PopupOnVisibleStateChange,
type PopupOnCancel,
type SelectorModelValue
} from '@/index'
import { formatter, parser, template } from '../Calendar/utils'
const popupValue = ref(dayjs().format(template))
const popupRangeValue = ref([])
const popupVisible = ref(false)
const popupRangeVisible = ref(false)
const popupShowConfirm = ref(false)
const popupShowClose = ref(false)
const confirmEvent = ref(false)
const visibleEvent = ref(false)
const title = 'CalendarPopup'
const onVisibleStateChange: PopupOnVisibleStateChange = res => {
if (visibleEvent.value) {
console.log('change', res)
showToast(`${res.state} 事件触发`)
}
if (res.state === 'hidden') {
visibleEvent.value = false
confirmEvent.value = false
popupShowConfirm.value = false
popupShowClose.value = false
}
}
const onCancel: PopupOnCancel = res => {
console.log('cancel', res)
if (confirmEvent.value) {
showToast(`触发了取消事件`)
}
}
const onConfirm: CalendarOnConfirm = res => {
console.log('confirm', res)
if (confirmEvent.value) {
showToast(`触发了确定事件`)
}
}
function onChange(res: SelectorModelValue) {
console.log('change', res)
// showToast(`change: ${res}`)
}
const onRangeConfirm: CalendarOnConfirm = res => {
console.log('confirm', res)
}
function addOneDay() {
popupValue.value = dayjs(popupValue.value, template, true).add(1, 'day').format(template)
}
</script>
<script lang="ts">
export default {
name: 'ExpCalendarPopup'
}
</script>
<template>
<ta-notice-bar class="top-notice-bar" title="基础展示参数可以参考 Calendar" />
<ta-group title="基础用法">
<ta-cell
label="默认"
@click="
() => {
popupVisible = true
}
"
>{{ popupValue }}</ta-cell
>
<ta-cell label="+1day" isLink @click="addOneDay">click</ta-cell>
<ta-cell
label="showConfirm=true"
isLink
@click="
() => {
popupShowConfirm = true
popupVisible = true
}
"
/>
<ta-cell label="initialMode=range" isLink @click="popupRangeVisible = true" />
</ta-group>
<ta-group title="事件监听">
<ta-cell
label="confirm/cancel"
isLink
@click="
() => {
confirmEvent = true
popupVisible = true
popupShowClose = true
}
"
/>
<ta-cell
label="visible-state-change"
isLink
@click="
() => {
visibleEvent = true
popupVisible = true
}
"
/>
</ta-group>
<ta-calendar-popup
v-model:visible="popupVisible"
:title="title"
:showConfirm="popupShowConfirm"
:showClose="popupShowClose"
v-model="popupValue"
:formatter="formatter"
:parser="parser"
@confirm="onConfirm"
@cancel="onCancel"
@change="onChange"
@visibleStateChange="onVisibleStateChange"
/>
<ta-calendar-popup
v-model:visible="popupRangeVisible"
:title="title"
initialMode="range"
v-model="popupRangeValue"
@confirm="onRangeConfirm"
/>
</template>
CalendarPopup Props
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| v-model:visible | boolean | false | 否 | 是否显示 |
| title | string | 否 | 弹窗标题 | |
| show-confirm | boolean | false | 否 | 选择时是否展示确定按钮 |
| show-close | boolean | false | 否 | 是否展示关闭按钮 |
CalendarPopup Events
| 事件 | 描述 | 回调函数参数 | 函数 TypeScript |
|---|---|---|---|
| confirm | 选择完毕后触发 / showConfirm 点击确定按钮后触发 | payload: CalendarDetail | CalendarOnConfirm |
| cancel | 点击蒙层关闭后触发 | PopupOnCancel | |
| change | 选择后值发生改变时触发 | payload: SelectorModelValue | SelectorOnChange |
| visible-state-change | 展示隐藏时触发 | payload: { state: VisibleState } | PopupOnVisibleStateChange |
VisibleState 值说明
| 值 | 说明 | 备注 |
|---|---|---|
| show | 展示时触发 | |
| shown | 展示且动画结束后触发 | |
| hide | 隐藏时触发 | 可能携带其他参数 cancel, maskClick, closeClick 等 |
| hidden | 隐藏且动画结束后触发 | 可能携带其他参数 cancel, maskClick, closeClick 等 |
CalendarView 日历选择面板
vue
<script setup lang="ts">
import { ref } from 'vue'
import { type CalendarOnSelect, showToast } from '@/index'
import { formatter, parser } from '../Calendar/utils'
const viewValue = ref('')
const viewRangeValue = ref('')
const onSelect: CalendarOnSelect = res => {
console.log('select', res)
showToast(`选择:${res.label}`)
}
</script>
<script lang="ts">
export default {
name: 'ExpCalendarView'
}
</script>
<template>
<ta-notice-bar class="top-notice-bar" title="基础展示参数可以参考 Calendar" />
<ta-group title="initialMode=single">
<ta-cell label="v-model"> {{ viewValue }} </ta-cell>
<ta-calendar-view v-model="viewValue" :formatter="formatter" :parser="parser" />
</ta-group>
<ta-group title="initialMode=range">
<ta-cell label="v-model"> {{ viewRangeValue }} </ta-cell>
<ta-calendar-view
initialMode="range"
v-model="viewRangeValue"
:formatter="formatter"
:parser="parser"
/>
</ta-group>
<ta-group title="select 事件">
<ta-calendar-view @select="onSelect" />
</ta-group>
</template>
CalendarView Events
| 事件 | 描述 | 回调函数参数 | 函数 TypeScript |
|---|---|---|---|
| select | 选择后触发 | payload: CalendarDetail | CalendarOnSelect |
| change | 选择后值发生改变时触发 | payload: SelectorModelValue | SelectorOnChange |
showCalendar(object) 显示日历选择弹窗
object
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|---|---|---|---|---|
| mode | CalendarMode | 'single' | 否 | 模式 |
| title | string | 否 | 弹窗标题 | |
| value | Date/Date[] | [] | 否 | 默认选择值,range 模式下需要提供两个 |
| minDate | Date | 当前日期 | 否 | 可选最小值 |
| maxDate | Date | 当前日期的六个月后 | 否 | 可选最大值 |
| allowSameDay | boolean | false | 否 | range 模式生效,设置开始结束时间是否可以同一天 |
| maxRange | number | Infinity | 否 | range 模式生效,选择区间的最长天数 |
| dayHandler | CalendarDayHandler | 否 | 日历每个日期处理函数 | |
| success | (payload: SuccessPayload) => void | 否 | 接口调用成功(在用户做出选择后,如取消,选择选项)的回调函数 | |
| fail | (e: Error) => void | 否 | 接口调用失败(如传入错误的参数)的回调函数(不传入 fail 遇错误直接抛出) | |
| complete | () => void | 否 | 弹窗关闭或调用失败的回调函数 |
SuccessPayload
| 属性 | 类型 | 说明 |
|---|---|---|
| confirm? | boolean | 为 true 时,表示点击了确定,此时返回 detail |
| cancel? | boolean | 为 true 时,表示取消 |
| detail? | CalendarDetail |
Usage
具体调用方式可以参考API 调用。
js
showCalendar({
type: 'range',
showClose: true,
success: ({ confirm, cancel, detail }) => {
...
}
})
类型释义
SelectorValue
ts
type SelectorValue = string | number | Date
SelectorModelValue
ts
type SelectorModelValue = SelectorValue | SelectorValue[]
注:在不自定义 formatter/parser 的情况下,v-model 只有 Date[] 这种情况。
CalendarDetail
ts
interface CalendarDetail {
label: string
value: Date[]
valueArray: number[][]
rangeCount: number
}
| 字段 | 说明 |
|---|---|
| label | 选中值对应的描述文本,如果设置了 formatter,则返回格式后文本 |
| value | 选择的值,range 模式下有开始 Date 和结束 Date 两个实例,不受 formatter 影响 |
| valueArray | 如:[[2021, 5, 1]] 或 [[2021, 5, 1], [2021, 5, 30]] |
| rangeCount | 选择区间持续的天数(含首尾) |
CalendarMode
ts
type CalendarMode = 'single' | 'range'
| 值 | 说明 |
|---|---|
| single | 选择一天 |
| range | 选择一个日期区间 |
CalendarValueFormatter
ts
interface CalendarValueFormatter {
(valueArray: Date[], mode: CalendarMode):
| { value: SelectorModelValue; label: string }
| SelectorModelValue
}
将 v-model 的原始值转为需要的自定义值,值需要满足 SelectorModelValue 的类型约束,可以返回 { value, label } 对两个数据进行修改,或者单独返回 value。
CalendarValueParser
ts
interface CalendarValueParser {
(value: unknown, mode: CalendarMode): Date[]
}
跟 CalendarValueFormatter 相反,将自定义 v-model 的值转为组件认识的原始数组。
CalendarDayHandler
ts
type CalendarDayHandler = dayHandler(dayInfo: DayInfo) => DayInfo
interface DayInfo {
topHighlight?: boolean
topText?: string
state: string
bottomHighlight?: boolean
bottomText?: string
text: string
dateString: string
date?: Date
timestamp: number
}
日历中的每个日期都对应一个 DayInfo 对象,通过 day-handler 属性可以修改 DayInfo 对象的内容后返回。
| 值 | 类型 | 说明 |
|---|---|---|
| date | Date | 日期对应的 Date 对象,该字段修改无效 |
| state | string | 日期当前的状态,有:selected 选中,startSelected 开始(initialMode="range"下),endSelected 结束(initialMode="range"下),disabled 禁用。在空字符串的情况下,可以设置为 disabled 强制设置该日期为禁用(一般在票卖完的情况下设置) |
| text | string | 日期文本,不建议修改 |
| topText | string | 日期上方展示文本,一般可修改为“节日名称”、“今天”、“明天”、“开始”、“结束”等 |
| topHighlight | boolean | 日期上方展示文本是否高亮 |
| bottomText | string | 日期下方展示文本,一般可修改为“机票价格”、“酒店价格”、“特价”、“热门”等 |
| bottomHighlight | boolean | 日期下方展示文本是否高亮 |
| dateString | string | 日期对应的格式化时间(YYYY-MM-DD),如:2020-11-11,该字段不影响展示 |