• Vant React

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>
    </>
  )
}

选择多个日期

设置 typemultiple 后可以选择多个日期,此时 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>
    </>
  )
}

选择日期区间

设置 typerange 后可以选择日期区间,此时 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" }} />

自定义日期范围

通过 minmax 定义日历的范围。

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 函数来对日历上每一格的内容进行格式化。

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 属性自定义弹出层的弹出位置,可选值为 topleftright

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 表示选择日期区间
stringsingle
defaultValue默认选中的日期,typemultiplerange 时为数组,传入 null 表示默认不选择Date | Date[] | null今天
value选中的日期,typemultiplerange 时为数组,传入 null 表示默认不选择Date | Date[] | null今天
formatter日期格式化函数(day: Calendar.DayObject) => Calendar.DayObject-
title日历标题ReactNode日期选择
showSubtitle是否展示日历副标题(年月)booleantrue
subtitle自定义日历副标题ReactNode|((date: Date) => ReactNode)(date) => `${date.getFullYear()}年${date.getMonth() + 1}月`
watermark是否显示月份背景水印booleantrue
min可选择的最小日期Date当前日期
max可选择的最大日期Date当前日期的六个月后
poppable是否以弹层的形式展示日历booleanfalse
showPopup是否显示日历弹窗, poppable: true时生效booleanfalse
popupPlacement弹出位置,可选值为 left right top , poppable: true时生效stringbottom
popupRound是否显示圆角弹窗, poppable: true时生效booleantrue
popupCloseIcon弹框是否显示关闭图标, poppable: true时生效booleantrue
readonly是否为只读状态,只读状态下不能选择日期booleanfalse
showConfirm是否展示确认按钮booleantrue
confirmText确认按钮的文字ReactNode确认
confirmDisabledText确认按钮处于禁用状态时的文字ReactNode确认
firstDayOfWeek设置周起始日0-60

Calendar.DayObject 数据结构

日历中的每个日期都对应一个 Day 对象,通过formatter属性可以自定义 Day 对象的内容

键名说明类型
date日期对应的 Date 对象Date
type日期类型,可选值为 active start middle end disabledstring
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按钮类型confirmconfirm
confirmText确认按钮的文字ReactNode-
confirmDisabledText确认按钮处于禁用状态时的文字ReactNode-

主题定制

样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。

名称默认值描述
—calendar-active-colorvar(—blue, $blue)-
—calendar-background-colorvar(—white)-
—calendar-header-box-shadow0 2px * $hd 10px * $hd rgba(125, 126, 128, 0.16)-
—calendar-header-title-height44px * $hd-
—calendar-header-title-font-sizevar(—font-size-lg)-
—calendar-header-subtitle-font-sizevar(—font-size-md)-
—calendar-weekdays-height30px * $hd-
—calendar-weekdays-font-sizevar(—font-size-sm)-
—calendar-month-title-font-sizevar(—font-size-md)-
—calendar-month-watermark-colorrgba(242, 243, 245, 0.8)-
—calendar-month-watermark-font-size160px * $hd-
—calendar-range-edge-colorvar(—white)-
—calendar-range-edge-background-colorvar(—calendar-active-color)-
—calendar-range-middle-colorvar(—calendar-active-color)-
—calendar-range-middle-background-opacity0.1-
—calendar-day-height64px * $hd-
—calendar-day-font-sizevar(—font-size-lg)-
—calendar-day-disabled-colorvar(—gray-5)-
—calendar-active-day-size54px * $hd-
—calendar-active-day-colorvar(—white)-
—calendar-active-day-background-colorvar(—calendar-active-color)-
—calendar-active-day-border-radiusvar(—border-radius-md)-
—calendar-day-info-font-sizevar(—font-size-xs)-
—calendar-day-info-line-heightvar(—line-height-xs)-
—calendar-confirm-button-height36px * $hd-
—calendar-confirm-button-margin7px * $hd 0-
—calendar-confirm-button-colorvar(—calendar-active-color)-
—calendar-footer-padding0 var(—padding-md)-