DateRangePicker 日期范围
一次选出「开始 ~ 结束」两端。面板并排展示两个月,选中开始日期后悬停即可预览整段区间。与 MDatePicker 共用同一套日期工具与 format 语义:format 里出现 H / mm / ss 时启用时间选择,输出数组两端都是 format 格式字符串(未选的一端为 null)。
代码演示
基础用法
v-model 绑定 [开始, 结束]。未选满两端时,另一端是 null;整体清空时绑定值为 null。
clearable 在两端都有值后显示清除按钮。
<script setup lang="ts">
import { ref } from 'vue'
const range = ref<[string | null, string | null] | null>(null)
</script>
<template>
<div class="m-row-demo--col">
<MDateRangePicker
v-model="range"
:placeholder="['开始', '结束']"
format="YYYY-MM-DD"
clearable />
<span>选中:{{ range ? `${range[0] ?? '未选'} ~ ${range[1] ?? '未选'}` : '未选择' }}</span>
</div>
</template>日期时间模式
format 含时间占位符时进入 datetime 模式,面板底部出现时钟按钮,可分别调整起止时间的时分秒。
点选日期不会立即关闭面板,需要点「确定」。
<script setup lang="ts">
import { ref } from 'vue'
const range = ref<[string | null, string | null] | null>(null)
function fmt(value: [string | null, string | null] | null) {
return value ? `${value[0] ?? '未选'} ~ ${value[1] ?? '未选'}` : '未选择'
}
</script>
<template>
<div class="m-row-demo--col">
<MDateRangePicker
v-model="range"
format="YYYY-MM-DD HH:mm"
:placeholder="['开始时间', '结束时间']"
clearable />
<span>选中:{{ fmt(range) }}</span>
</div>
</template>自定义占位符与格式
placeholder 传单个字符串时两格共用,传二元组时分别用于开始 / 结束。format 决定回写的字符串格式。
最后两条分别展示两种占位符写法与两种输出格式。
<script setup lang="ts">
import { ref } from 'vue'
const single = ref<[string | null, string | null] | null>(null)
const pair = ref<[string | null, string | null] | null>(null)
function fmt(value: [string | null, string | null] | null) {
return value ? `${value[0] ?? '未选'} ~ ${value[1] ?? '未选'}` : '未选择'
}
</script>
<template>
<div class="m-row-demo--col">
<MDateRangePicker v-model="single" placeholder="请选择日期区间" format="YYYY/MM/DD" />
<MDateRangePicker v-model="pair" :placeholder="['入住', '离店']" format="YYYY-MM-DD" />
<span>单个字符串:{{ fmt(single) }}</span>
<span>数组分别指定:{{ fmt(pair) }}</span>
</div>
</template>尺寸与圆角
size 三档;radius 改触发区圆角,panelRadius 改弹出面板圆角,width 改触发区宽度。
<script setup lang="ts">
import { ref } from 'vue'
const small = ref<[string | null, string | null] | null>(null)
const normal = ref<[string | null, string | null] | null>(null)
const large = ref<[string | null, string | null] | null>(null)
const rounded = ref<[string | null, string | null] | null>(null)
</script>
<template>
<div class="m-row-demo--col">
<div class="m-row-demo">
<MDateRangePicker v-model="small" size="small" :placeholder="['小', '小']" />
<MDateRangePicker v-model="normal" size="default" :placeholder="['默认', '默认']" />
<MDateRangePicker v-model="large" size="large" :placeholder="['大', '大']" />
</div>
<MDateRangePicker
v-model="rounded"
width="280px"
radius="999px"
panel-radius="16px"
:placeholder="['自定义宽度', '自定义圆角']" />
</div>
</template>可选范围与禁用
min / max 限定两端可选区间;disabled 整体禁用。
min / max 接受 Date 或可解析字符串。
<script setup lang="ts">
import { ref } from 'vue'
function pad(value: number) {
return value < 10 ? `0${value}` : String(value)
}
function ymd(date: Date) {
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
}
const today = new Date()
const min = ymd(today)
const max = ymd(new Date(today.getFullYear(), today.getMonth() + 2, today.getDate()))
const inRange = ref<[string | null, string | null] | null>(null)
const locked = ref<[string | null, string | null] | null>(null)
function fmt(value: [string | null, string | null] | null) {
return value ? `${value[0] ?? '未选'} ~ ${value[1] ?? '未选'}` : '未选择'
}
</script>
<template>
<div class="m-row-demo--col">
<MDateRangePicker
v-model="inRange"
:min="min"
:max="max"
:placeholder="['今天起', '两个月内']"
clearable />
<MDateRangePicker v-model="locked" disabled :placeholder="['禁用', '禁用']" />
<span>范围内选中:{{ fmt(inRange) }}</span>
<span>禁用态值:{{ fmt(locked) }}</span>
</div>
</template>API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue | DateRangeValue | undefined | 当前值(v-model):[开始, 结束] |
placeholder | string | [string, string] | '开始日期 ~ 结束日期' | 占位符:单个字符串同时用于两格,数组则分别用于开始 / 结束 |
format | string | 'YYYY-MM-DD' | 输出格式模板,同时决定是否启用时间选择 |
disabled | boolean | false | 是否禁用 |
clearable | boolean | false | 有值时显示清除按钮 |
size | 'small' | 'default' | 'large' | 'default' | 尺寸 |
min | Date | string | undefined | 可选最小日期 |
max | Date | string | undefined | 可选最大日期 |
appendToBody | boolean | true | 挂载到 body |
popupPlacement | 'top' | 'bottom' | 'bottom' | 弹出方向(空间不足时自动翻转) |
width | string | undefined | 触发区宽度 |
radius | string | undefined | 触发区圆角(任意 CSS 长度);默认 4px |
panelRadius | string | undefined | 弹出面板圆角(任意 CSS 长度);默认 4px |
name | string | undefined | 原生 input name(表单提交) |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
update:modelValue | value: [string | null, string | null] | null | 范围变化(各端为 format 字符串,未选为 null),清空时为 null |
change | value: [string | null, string | null] | null | 范围变化 |
open | 无 | 面板打开 |
close | 无 | 面板关闭 |
Slots
无。
类型定义
type DateRangeValue =
| [Date | string | null, Date | string | null]
| null范围选择规则
- 当前无选择、或已选满两端时再次点击,会以该点为新的开始日期;
- 已有开始日期、再点击更早的日期,会把开始日期替换为新的这一天;
- 已有开始日期、再点击更晚的日期,补全结束日期,完成本次选择。
使用建议
输出是数组,不是拼接字符串
回写值形如 ['2026-09-01', '2026-09-30'],两端都可能为 null;「整体为 null」表示两侧都被清除。处理时先判 null 再取下标,不要把 [null, null] 当成有效范围。
与 DatePicker 保持同一套 format
两个组件的 format 语义完全一致,同一页面内建议统一,避免日期与区间出现不同分隔符或不同时间精度。
小写 mm 仍是「分」
和 MDatePicker 一样,MM(月)与 mm(分)区分大小写,format 里出现 mm 就会进入时间模式。只想要日期就用 YYYY/MM/DD 这类不含 H、mm、ss 的模板。
没有内置的「最近 7 天」快捷预设
面板只提供年 / 月快捷跳转,以及底部的「清除」「确定」。要「今天 / 近 7 天 / 本月」这类相对区间,需要业务侧算好两端日期后写进 v-model。
相关组件
- DatePicker 日期选择:只需要选单个日期时使用。
- Input 输入框:只需要自由文本输入、不做日期约束时使用。
- Select 选择器:取值来自固定几项时使用。