ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vant DatePicker 日期选择器完全指南:从基础用法到源码级原理

Vant DatePicker 日期选择器完全指南:从基础用法到源码级原理 Vant DatePicker 日期选择器完全指南从基础用法到源码级原理【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vantVant 的 DatePicker 组件用于在移动端选择年、月、日是一个基于 Picker 封装的日期滚轮选择器通常与 Popup 弹出层 组件配合使用。本文以 Vant 仓库中 DatePicker 官方文档 为主体结合 组件源码、工具函数 与 测试用例系统讲解组件引入、基础用法、选项类型组合、格式化与过滤以及底层选项生成与日期边界钳制的实现原理帮助你彻底掌握这一组件的使用与二次开发能力。组件介绍与引入DatePicker 是 Vant 提供的日期选择器用来让用户从滚轮中选取年、月、日。它内部复用了 Picker 选择器 的滚动交互与工具栏结构因此二者在属性、事件与插槽上高度一致学习成本可以复用。在 Vue 3 项目中可以通过app.use全局注册组件import { createApp } from vue; import { DatePicker } from vant; const app createApp(); app.use(DatePicker);注册完成后即可在模板中使用van-date-picker标签。更多的组件注册方式局部注册、自动按需引入等可以参考 组件注册 文档。从源码看组件通过withInstall包装后导出见 index.ts并同时在vue模块声明了VanDatePicker的全局组件类型方便 TypeScript 用户在模板中获得类型提示。基础用法v-model 与日期范围DatePicker 通过v-model绑定当前选中的日期值为字符串数组每个元素对应一列选中的值如[2021, 01, 01]。通过min-date与max-date两个Date类型的属性设定可选时间范围超出范围的选项不会被渲染。van-date-picker v-modelcurrentDate title选择日期 :min-dateminDate :max-datemaxDate /import { ref } from vue; export default { setup() { const currentDate ref([2021, 01, 01]); return { minDate: new Date(2020, 0, 1), maxDate: new Date(2025, 5, 1), currentDate, }; }, };从 DatePicker.tsx 的 props 定义可以看出两个边界属性的默认值并非写死而是以当前年份为基准动态计算min-date默认值为十年前 1 月 1 日new Date(currentYear - 10, 0, 1)max-date默认值为十年后 12 月 31 日new Date(currentYear 10, 11, 31)。两个属性都带有validator: isDate校验传入非法值会在开发环境下告警。由于边界精确到日月份列与日期列的具体取值范围会随选中年份、月份动态收窄这一点在下方选项生成原理一节会结合源码详细展开。选项类型columns-type 自由组合默认情况下 DatePicker 渲染年、月、日三列。通过columns-type属性可以控制列的类型支持以任意顺序对year、month、day三种类型进行排列组合。例如传入[year]只选择年份传入[month]只选择月份传入[year, month]选择年份和月份传入[month, day]选择月份和日期。van-date-picker v-modelcurrentDate title选择年月 :min-dateminDate :max-datemaxDate :columns-typecolumnsType /import { ref } from vue; export default { setup() { const currentDate ref([2021, 01]); const columnsType [year, month]; return { minDate: new Date(2020, 0, 1), maxDate: new Date(2025, 5, 1), currentDate, columnsType, }; }, };源码中columns-type的默认值为[year, month, day]类型为DatePickerColumnType[]见 DatePicker.tsx。组件会遍历columnsType数组依次生成对应列见columns计算属性如果传入数组之外的非法类型开发环境下会抛出[Vant] DatePicker: unsupported columns type错误生产环境则忽略该列。在 demo/index.vue 中可以找到[year, month]组合的完整可运行示例。注意columns-type改变后v-model的数组长度也要与之匹配。例如只选年月时绑定的值应为[2021, 01]两位数组。格式化选项formatterformatter是一个选项格式化函数签名是(type: string, option: PickerOption) PickerOption其中type为当前列的类型year/month/dayoption为待格式化的选项对象含text与value字段。在函数中修改option.text即可改变展示文字典型用途是拼接年/月/日单位后缀van-date-picker v-modelcurrentDate title选择年月 :min-dateminDate :max-datemaxDate :formatterformatter :columns-typecolumnsType /import { ref } from vue; export default { setup() { const currentDate ref([2021, 01]); const columnsType [year, month]; const formatter (type, option) { if (type year) { option.text 年; } if (type month) { option.text 月; } return option; }; return { minDate: new Date(2020, 0, 1), maxDate: new Date(2025, 5, 1), formatter, currentDate, columnsType, }; }, };从源码看formatter的默认实现是一个直接返回原 option 的恒等函数见 utils.ts所以不传时选项文本就是补零后的数字本身。formatter与filter的执行顺序是先生成、后过滤genOptions中先对每个数字执行formatter生成{ text, value }再交给filter处理见 utils.ts。测试用例 index.spec.ts 验证了 formatter 会为选项文本追加类型后缀的行为。过滤选项filterfilter是一个选项过滤函数签名是(type: string, options: PickerOption[], values: string[]) PickerOption[]。它接收当前列类型、该列全部选项数组以及当前选中的值数组返回过滤后的选项数组适合实现自定义选项间隔、排除特定日期等需求van-date-picker v-modelcurrentDate title选择年月 :filterfilter :min-dateminDate :max-datemaxDate :columns-typecolumnsType /import { ref } from vue; export default { setup() { const currentDate ref([2021, 01]); const columnsType [year, month]; const filter (type, options) { if (type month) { return options.filter((option) Number(option.value) % 6 0); } return options; }; return { filter, minDate: new Date(2020, 0, 1), maxDate: new Date(2025, 5, 1), currentTime, columnsType, }; }, };上面示例对月份列做了% 6 0的整除过滤相当于只保留 6 月与 12 月两个月份选项从而实现每半年选一次的间隔效果。测试中同样验证了 filter 对选项的裁剪行为见 index.spec.ts。需要留意过滤会直接影响选项的下标而v-model中的值必须仍然落在过滤后选项集合内否则组件会通过内部的formatValueRange将值钳制到有效范围内详见下文原理部分。API 详解Props参数说明类型默认值v-model当前选中的日期string[][]columns-type选项类型由year、month和day组成的数组string[][year, month, day]min-date可选的最小时间精确到日Date十年前max-date可选的最大时间精确到日Date十年后title顶部栏标题stringconfirm-button-text确认按钮文字string确认cancel-button-text取消按钮文字string取消show-toolbar是否显示顶部栏booleantrueloading是否显示加载状态booleanfalsereadonly是否为只读状态只读状态下无法切换选项booleanfalsefilter选项过滤函数(type: string, options: PickerOption[], values: string[]) PickerOption[]-formatter选项格式化函数(type: string, option: PickerOption) PickerOption-option-height选项高度支持pxvwvhrem单位默认pxnumber | string44visible-option-num可见的选项个数number | string6swipe-duration快速滑动时惯性滚动的时长单位msnumber | string1000其中loading、readonly、option-height、visible-option-num、swipe-duration、show-toolbar等来自 Picker 的共享属性定义见 Picker.tsxfilter、formatter、v-model则定义在 date-picker/utils.ts 的sharedProps中。DatePicker 会把继承自 Picker 的属性通过pickerInheritKeys白名单透传给内部的 Picker 组件见 DatePicker.tsx。Events事件名说明回调参数confirm点击完成按钮时触发{ selectedValues, selectedOptions, selectedIndexes }cancel点击取消按钮时触发{ selectedValues, selectedOptions, selectedIndexes }change选项改变时触发{ selectedValues, selectedOptions, selectedIndexes, columnIndex }其中selectedValues为各列选中值组成的数组selectedOptions为对应的选项对象数组selectedIndexes为各列选中项的下标change事件额外携带columnIndex表明是哪一列发生了变化。这三个事件类型在 picker/types.ts 中定义为PickerConfirmEventParams、PickerCancelEventParams与PickerChangeEventParams。测试用例 index.spec.ts 对 confirm、cancel 事件的参数结构做了完整断言。Slots名称说明参数toolbar自定义整个顶部栏的内容-title自定义标题内容-confirm自定义确认按钮内容-cancel自定义取消按钮内容-option自定义选项内容option: PickerOption, index: numbercolumns-top自定义选项上方内容-columns-bottom自定义选项下方内容-DatePicker 会将外部传入的插槽原样透传给内部的 Picker 组件v-slots{slots}因此工具栏、标题、按钮、选项以及选项上下方内容都可以完全自定义。方法通过 ref 可以获取到 Picker 实例并调用实例方法详见 组件实例方法。方法名说明参数返回值confirm停止惯性滚动并触发confirm事件--getSelectedDate获取当前选中的日期-string[]类型定义组件导出以下类型定义import type { DatePickerProps, DatePickerColumnType, DatePickerInstance, } from vant;DatePickerInstance是组件实例的类型用法如下import { ref } from vue; import type { DatePickerInstance } from vant; const datePickerRef refDatePickerInstance(); datePickerRef.value?.confirm();从源码看DatePickerInstance通过ComponentPublicInstanceDatePickerProps, DatePickerExpose组合了组件属性与暴露的方法类型而confirm与getSelectedDate两个方法通过useExpose暴露给父组件见 DatePicker.tsx。源码级原理剖析选项生成流程DatePicker 的核心是三个选项生成函数见 DatePicker.tsxgenYearOptions从min-date的年份到max-date的年份生成逐年选项genMonthOptions先取当前选中年份若该年份正好是min-date所在年份则起始月为min-date的月份否则从 1 月开始同理若正好是max-date所在年份则截止月为max-date的月份否则到 12 月genDayOptions在选中年、月的基础上进一步收窄若是边界年月则取min-date/max-date的日否则通过getMonthEndDay(year, month)计算当月最后一天。所有选项最终统一走genOptions见 utils.ts用times生成连续整数序列通过padZero对个位数补零得到text与value如01、02再依次执行formatter与filter。这正是v-model值始终是补零字符串数组的原因。每月天数与大小月计算getMonthEndDay是一个巧妙的纯函数实现见 utils.tsconst getMonthEndDay (year: number, month: number): number 32 - new Date(year, month - 1, 32).getDate();它利用 JavaScript Date 的溢出回绕特性构造new Date(year, month - 1, 32)时第 32 天必然溢出到下个月getDate()返回的就是下个月的余数日期用 32 减去它即可得到当月天数。以 2 月为例new Date(2021, 1, 32)实际会解析为 3 月 4 日2021 年非闰年32 - 4 28恰好是 2 月的天数闰年 2 月则为 29。这样无需任何月份天数表即可正确处理大小月与闰年。值范围钳制formatValueRange当外部传入的modelValue超出当前列的实际范围时例如 max-date 为 2010 年却传入[2020, 10, 10]组件会调用formatValueRange将每个值clamp到该列第一个与最后一个选项之间见 utils.ts。测试用例验证了这一行为传入越界的[2020, 10, 10]后点击确认最终得到的selectedValues是[2010, 01, 10]见 index.spec.ts。这意味着即使业务数据越界组件也能优雅地回落到合法范围不会出现空白选中态。与 Picker 的协作关系DatePicker 本质上是 Picker 的数据适配层它负责把日期领域概念年、月、日、边界、格式化、过滤翻译成 Picker 需要的通用PickerOption[]列结构然后把渲染、滚动、惯性动画、工具栏交互全部交给 Picker 完成见 DatePicker.tsx。PickerOption类型定义在 picker/types.ts包含text、value、disabled、children等字段。理解这一分层后若要实现季度选择星期选择等自定义选择器完全可以参照 DatePicker 的模式基于 Picker 自行封装。常见问题设置 min-date 或 max-date 后出现页面卡死的情况请不要在模板中直接使用类似min-datenew Date()的写法这样会导致每次渲染组件时传入一个新的 Date 对象而传入新的数据会触发下一次渲染从而陷入死循环。正确的做法是将min-date作为一个数据定义在data函数或setup中。在 iOS 系统上初始化组件失败如果你遇到了在 iOS 上无法渲染组件的问题请确认在创建 Date 对象时没有使用new Date(2020-01-01)这样的写法iOS 不支持以中划线分隔的日期格式正确写法是new Date(2020/01/01)。在桌面端无法操作组件DatePicker 依赖触摸事件完成滚轮滑动在桌面端使用时需要启用 Vant 的桌面端适配能力具体做法参见 桌面端适配 文档或引入vant/touch-emulator将鼠标事件模拟为触摸事件。结语本文从引入、基础用法到columns-type组合、formatter格式化、filter过滤再到选项生成、大小月计算与值钳制的源码实现完整覆盖了 Vant DatePicker 的使用与原理。实际项目中建议结合 官方演示代码 快速起步并复用 测试用例 中验证过的边界场景min-date / max-date 越界、外部动态更新 modelValue 等来指导业务联调。如果还需要联动日期区间选择可以在此基础上进一步组合两个 DatePicker 实例与 Popup 实现起止日期选择。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表