#Calendar 日历
#介绍
日历组件用于选择日期或日期区间。如要以弹层形式展示, 请使用 poppable,不要手动嵌套
#引入
import { Calendar } from "@taroify/core"#代码演示
#选择单个日期
下面演示了结合单元格来使用日历组件的用法,日期选择完成后会触发 onConfirm 事件。
function formatFullDate(date?: Date) {
if (date) {
return `${date.getFullYear()}/${formatDate(date)}`
}
}
function SingleCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="选择单个日期" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="single"
value={value}
poppable
showPopup={open}
onClose={setOpen}
onChange={setValue}
onConfirm={(newValue) => {
setOpen(false)
setFormatValue(formatFullDate(newValue))
}}
></Calendar>
</>
)
}#选择多个日期
设置 type 为 multiple 后可以选择多个日期,此时 onConfirm 事件处理 value 数组结构,数组包含若干个选中的日期。
function formatMultiple(dates: Date[]) {
if (dates.length) {
return `选择了 ${dates.length} 个日期`
}
}
function MultipleCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date[]>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="选择多个日期" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="multiple"
value={value}
poppable
showPopup={open}
onClose={setOpen}
onChange={setValue}
onConfirm={(newValue) => {
setFormatValue(formatMultiple(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#选择日期区间
设置 type 为 range 后可以选择日期区间,此时 onConfirm 事件处理 value 数组结构,数组第一项为开始时间,第二项为结束时间。
function formatRange(dateRange: Date[]) {
if (dateRange.length) {
const [start, end] = dateRange
return `${formatDate(start)} - ${formatDate(end)}`
}
}
function RangeCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date[]>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="选择日期区间" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="range"
value={value}
onChange={setValue}
poppable
showPopup={open}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatRange(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#快捷选择
将 showConfirm 设置为 false 可以隐藏确认按钮,这种情况下选择完成后会立即触发 confirm 事件。
function SingleQuicklyCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="选择单个日期" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="single"
value={value}
onChange={setValue}
poppable
showPopup={open}
showConfirm={false}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatFullDate(newValue))
setOpen(false)
}}
/>
</>
)
}#自定义颜色
通过 css 可以自定义日历的颜色,对选中日期和底部按钮生效。
<Calendar style={{ "--calendar-active-color": "red" }} />#自定义日期范围
通过 min 和 max 定义日历的范围。
function CustomRangeCalendar() {
const [minDate] = useState(new Date(2010, 0, 1))
const [maxDate] = useState(new Date(2010, 0, 31))
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date[]>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义日期范围" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="range"
min={minDate}
max={maxDate}
value={value}
onChange={setValue}
poppable
showPopup={open}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatRange(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#自定义按钮文字
通过 confirmText 设置按钮文字,通过 confirmDisabledText 设置按钮禁用时的文字。
function CustomConfirmCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date[]>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义按钮" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="range"
value={value}
onChange={(newValue) => {
setValue(newValue)
}}
poppable
showPopup={open}
confirmDisabledText="请选择结束时间"
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatRange(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#自定义日期文案
通过传入 formatter 函数来对日历上每一格的内容进行格式化。
const dayFormatter = (day: Calendar.DayObject) => {
if (!day.value) {
return day
}
const month = day.value.getMonth() + 1
const date = day.value.getDate()
if (month === 5) {
if (date === 1) {
day.top = "劳动节"
} else if (date === 4) {
day.top = "青年节"
} else if (date === 11) {
day.children = "今天"
}
}
if (day.type === "start") {
day.bottom = "入店"
} else if (day.type === "end") {
day.bottom = "离店"
} else if (day.type === "active") {
day.bottom = "入店/离店"
}
return day
}
function CustomDayCalendar() {
const [open, setOpen] = useState(false)
const [minDate] = useState(new Date(2010, 4, 1))
const [maxDate] = useState(new Date(2010, 4, 31))
const [value, setValue] = useState<Date[]>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义日期文案" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="range"
min={minDate}
max={maxDate}
formatter={dayFormatter}
value={value}
onChange={setValue}
poppable
showPopup={open}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatRange(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#自定义弹出位置
通过 placement 属性自定义弹出层的弹出位置,可选值为 top、left、right。
function CustomPositionCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义弹出位置" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
popupPlacement="right"
type="single"
value={value}
onChange={setValue}
poppable
showPopup={open}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatFullDate(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#自定义周起始日
通过 firstDayOfWeek 属性设置一周从哪天开始。
function CustomFirstDayOfWeekCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date>()
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义周起始日" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
popupCloseIcon={false}
popupRounded={false}
type="single"
value={value}
onChange={setValue}
poppable
showPopup={open}
onClose={setOpen}
firstDayOfWeek={1}
onConfirm={(newValue) => {
setFormatValue(formatFullDate(newValue))
setOpen(false)
}}
></Calendar>
</>
)
}#平铺展示
将 poppable 设置为 false,日历会直接展示在页面内,而不是以弹层的形式出现。
function TiledCalendar() {
const [minDate] = useState(new Date(2012, 1, 10))
const [maxDate] = useState(new Date(2012, 10, 20))
const [value, setValue] = useState<Date>()
return (
<Calendar
style={{ height: "500px" }}
title="日历"
min={minDate}
max={maxDate}
value={value}
onChange={setValue}
/>
)
}#手动控制 Footer DOM
通过 Calendar.Footer Calendar.Button 手动控制 Footer DOM。
function CustomConfirmCalendar() {
const [open, setOpen] = useState(false)
const [value, setValue] = useState<Date[]>()
const [confirm, setConfirm] = useState("请选择结束时间")
const [formatValue, setFormatValue] = useState<string>()
return (
<>
<Cell title="自定义按钮" isLink children={formatValue} onClick={() => setOpen(true)} />
<Calendar
type="range"
value={value}
onChange={(newValue) => {
setValue(newValue)
setConfirm(newValue.length === 2 ? "完成" : "请选择结束时间")
}}
poppable
showPopup={open}
onClose={setOpen}
onConfirm={(newValue) => {
setFormatValue(formatRange(newValue))
setOpen(false)
}}
>
<Calendar.Footer>
<Calendar.Button type="confirm">{confirm}</Calendar.Button>
</Calendar.Footer>
</Calendar>
</>
)
}#API
#Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 选择类型:single 表示选择单个日期,multiple 表示选择多个日期,range 表示选择日期区间 | string | single |
| defaultValue | 默认选中的日期,type 为 multiple 或 range 时为数组,传入 null 表示默认不选择 | Date | Date[] | null | 今天 |
| value | 选中的日期,type 为 multiple 或 range 时为数组,传入 null 表示默认不选择 | Date | Date[] | null | 今天 |
| formatter | 日期格式化函数 | (day: Calendar.DayObject) => Calendar.DayObject | - |
| title | 日历标题 | ReactNode | 日期选择 |
| showSubtitle | 是否展示日历副标题(年月) | boolean | true |
| subtitle | 自定义日历副标题 | ReactNode|((date: Date) => ReactNode) | (date) => `${date.getFullYear()}年${date.getMonth() + 1}月` |
| watermark | 是否显示月份背景水印 | boolean | true |
| min | 可选择的最小日期 | Date | 当前日期 |
| max | 可选择的最大日期 | Date | 当前日期的六个月后 |
| poppable | 是否以弹层的形式展示日历 | boolean | false |
| showPopup | 是否显示日历弹窗, poppable: true 时生效 | boolean | false |
| popupPlacement | 弹出位置,可选值为 left right top , poppable: true 时生效 | string | bottom |
| popupRound | 是否显示圆角弹窗, poppable: true 时生效 | boolean | true |
| popupCloseIcon | 弹框是否显示关闭图标, poppable: true 时生效 | boolean | true |
| readonly | 是否为只读状态,只读状态下不能选择日期 | boolean | false |
| showConfirm | 是否展示确认按钮 | boolean | true |
| confirmText | 确认按钮的文字 | ReactNode | 确认 |
| confirmDisabledText | 确认按钮处于禁用状态时的文字 | ReactNode | 确认 |
| firstDayOfWeek | 设置周起始日 | 0-6 | 0 |
#Calendar.DayObject 数据结构
日历中的每个日期都对应一个 Day 对象,通过formatter属性可以自定义 Day 对象的内容
| 键名 | 说明 | 类型 |
|---|---|---|
| value | 日期对应的 Date 对象 | Date |
| type | 日期类型,可选值为 active start middle end disabled | string |
| children | 中间显示的文字 | string |
| top | 上方的提示信息 | string |
| bottom | 下方的提示信息 | string |
| className | 额外类名 | string |
#Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| onChange | 点击并选中任意日期时触发 | value: Date | Date[] |
| onConfirm | 日期选择完成后触发,若使用 Calendar.Button 组件,则点击确认按钮后触发 | value: Date | Date[] |
| onClose | 关闭弹层时出发 | visible: boolean |
#Calendar.Footer Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| children | 底部内容 | ReactNoe | - |
#Calendar.Button Props
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| children | 按钮内容 | ReactNoe | 确认 |
| type | 按钮类型 | confirm | confirm |
| confirmText | 确认按钮的文字 | ReactNode | - |
| confirmDisabledText | 确认按钮处于禁用状态时的文字 | ReactNode | - |
#主题定制
#样式变量
组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。
| 名称 | 默认值 | 描述 |
|---|---|---|
| --calendar-active-color | var(--blue, $blue) | - |
| --calendar-background-color | var(--white) | - |
| --calendar-header-box-shadow | 0 2px * $hd 10px * $hd rgba(125, 126, 128, 0.16) | - |
| --calendar-header-title-height | 44px * $hd | - |
| --calendar-header-title-font-size | var(--font-size-lg) | - |
| --calendar-header-subtitle-font-size | var(--font-size-md) | - |
| --calendar-weekdays-height | 30px * $hd | - |
| --calendar-weekdays-font-size | var(--font-size-sm) | - |
| --calendar-month-title-font-size | var(--font-size-md) | - |
| --calendar-month-watermark-color | rgba(242, 243, 245, 0.8) | - |
| --calendar-month-watermark-font-size | 160px * $hd | - |
| --calendar-range-edge-color | var(--white) | - |
| --calendar-range-edge-background-color | var(--calendar-active-color) | - |
| --calendar-range-middle-color | var(--calendar-active-color) | - |
| --calendar-range-middle-background-opacity | 0.1 | - |
| --calendar-day-height | 64px * $hd | - |
| --calendar-day-font-size | var(--font-size-lg) | - |
| --calendar-day-disabled-color | var(--gray-5) | - |
| --calendar-active-day-size | 54px * $hd | - |
| --calendar-active-day-color | var(--white) | - |
| --calendar-active-day-background-color | var(--calendar-active-color) | - |
| --calendar-active-day-border-radius | var(--border-radius-md) | - |
| --calendar-day-info-font-size | var(--font-size-xs) | - |
| --calendar-day-info-line-height | var(--line-height-xs) | - |
| --calendar-confirm-button-height | 36px * $hd | - |
| --calendar-confirm-button-margin | 7px * $hd 0 | - |
| --calendar-confirm-button-color | var(--calendar-active-color) | - |
| --calendar-footer-padding | 0 var(--padding-md) | - |