介绍
组合了日历、弹出框组件,实现了便捷快速的日历选择功能。
引入
js
import CalendarPopout from 'sard-uniapp/components/calendar-popout/calendar-popout.vue'代码演示
基础使用
使用 v-model 双向绑定当前值,使用 v-model:visible 控制弹出框显隐。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
@change="onChange"
/>
<sar-list card>
<sar-list-item>
<sar-button @click="visible = true">
{{ value ? formatDate(value, 'YYYY-MM-DD') : '请选择' }}
</sar-button>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item title="设置为今天" arrow hover @click="value = new Date()" />
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { formatDate } from 'sard-uniapp'
const value = ref<Date | undefined>(new Date())
const visible = ref(false)
const onChange = (value: any) => {
console.log('change', value)
}
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
@change="onChange"
/>
<sar-list card>
<sar-list-item>
<sar-button @click="visible = true">
{{ value ? formatDate(value, 'YYYY-MM-DD') : '请选择' }}
</sar-button>
</sar-list-item>
<sar-list-item
title="当前值:"
:value="JSON.stringify(value) ?? 'undefined'"
/>
<sar-list-item title="设置为今天" arrow hover @click="value = new Date()" />
<sar-list-item title="清空" arrow hover @click="value = undefined" />
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref(/* @__PURE__ */ new Date());
const visible = ref(false);
const onChange = (value2) => {
console.log("change", value2);
};
</script>类型
日历组件可以选择单个值、多个值以及进行范围选择。
vue
<template>
<sar-calendar-popout
v-model="singleValue"
v-model:visible="singleVisible"
title="单个日期"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="mulitpleValue"
v-model:visible="mulitpleVisible"
type="multiple"
title="多个日期"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="rangeValue"
v-model:visible="rangeVisible"
type="range"
title="范围选择"
value-format="YYYY-MM-DD"
allow-same-day
/>
<sar-list card>
<sar-list-item
title="单个日期"
arrow
hover
:value="JSON.stringify(singleValue)"
@click="singleVisible = true"
/>
<sar-list-item
title="多个日期"
arrow
hover
:value="JSON.stringify(mulitpleValue)"
@click="mulitpleVisible = true"
/>
<sar-list-item
title="范围选择"
arrow
hover
:value="JSON.stringify(rangeValue)"
@click="rangeVisible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const singleValue = ref<string>()
const mulitpleValue = ref<string[]>()
const rangeValue = ref<string[]>()
const singleVisible = ref(false)
const mulitpleVisible = ref(false)
const rangeVisible = ref(false)
</script>vue
<template>
<sar-calendar-popout
v-model="singleValue"
v-model:visible="singleVisible"
title="单个日期"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="mulitpleValue"
v-model:visible="mulitpleVisible"
type="multiple"
title="多个日期"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="rangeValue"
v-model:visible="rangeVisible"
type="range"
title="范围选择"
value-format="YYYY-MM-DD"
allow-same-day
/>
<sar-list card>
<sar-list-item
title="单个日期"
arrow
hover
:value="JSON.stringify(singleValue)"
@click="singleVisible = true"
/>
<sar-list-item
title="多个日期"
arrow
hover
:value="JSON.stringify(mulitpleValue)"
@click="mulitpleVisible = true"
/>
<sar-list-item
title="范围选择"
arrow
hover
:value="JSON.stringify(rangeValue)"
@click="rangeVisible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const singleValue = ref();
const mulitpleValue = ref();
const rangeValue = ref();
const singleVisible = ref(false);
const mulitpleVisible = ref(false);
const rangeVisible = ref(false);
</script>自定义日期范围
可以使用 min 和 max 属性限制可以选择的日期的范围。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:min="new Date(2000, 0, 7)"
:max="new Date(2000, 0, 21)"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<string>()
const visible = ref(false)
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:min="new Date(2000, 0, 7)"
:max="new Date(2000, 0, 21)"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref();
const visible = ref(false);
</script>最多选择天数
在多个值和范围选择中,使用 maxDays 属性可以限制最多可选的天数。 超出允许选择的天数后会调用 overMaxDays 属性配置的函数。
vue
<template>
<sar-calendar-popout
v-model="mulitpleValue"
v-model:visible="mulitpleVisible"
title="多个日期"
type="multiple"
:max-days="3"
:over-max-days="() => toast('最多选择3天')"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="rangeValue"
v-model:visible="rangeVisible"
title="范围选择"
type="range"
:max-days="3"
:over-max-days="() => toast('最多选择3天')"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="多个日期"
arrow
hover
:value="JSON.stringify(mulitpleValue)"
@click="mulitpleVisible = true"
/>
<sar-list-item
title="范围选择"
arrow
hover
:value="JSON.stringify(rangeValue)"
@click="rangeVisible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { toast } from 'sard-uniapp'
import { ref } from 'vue'
const mulitpleValue = ref<Date[]>()
const rangeValue = ref<Date[]>()
const mulitpleVisible = ref(false)
const rangeVisible = ref(false)
</script>vue
<template>
<sar-calendar-popout
v-model="mulitpleValue"
v-model:visible="mulitpleVisible"
title="多个日期"
type="multiple"
:max-days="3"
:over-max-days="() => toast('最多选择3天')"
value-format="YYYY-MM-DD"
/>
<sar-calendar-popout
v-model="rangeValue"
v-model:visible="rangeVisible"
title="范围选择"
type="range"
:max-days="3"
:over-max-days="() => toast('最多选择3天')"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="多个日期"
arrow
hover
:value="JSON.stringify(mulitpleValue)"
@click="mulitpleVisible = true"
/>
<sar-list-item
title="范围选择"
arrow
hover
:value="JSON.stringify(rangeValue)"
@click="rangeVisible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const mulitpleValue = ref();
const rangeValue = ref();
const mulitpleVisible = ref(false);
const rangeVisible = ref(false);
</script>禁用日期
disabledDate 属性配置的函数接收一个日期对象,如果此函数返回真则禁用这个日期。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:disabled-date="disabledDate"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<Date>()
const visible = ref(false)
const disabledDate = (date: Date) => {
return /0|6/.test(String(date.getDay()))
}
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:disabled-date="disabledDate"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref();
const visible = ref(false);
const disabledDate = (date) => {
return /0|6/.test(String(date.getDay()));
};
</script>自定义起始周
默认一周从星期天开始,使用 weekStartsOn 属性可以配置一周从任意星期开始。 0 表示从周日开始,1 表示从周一开始。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:week-starts-on="1"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<Date>()
const visible = ref(false)
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
:week-starts-on="1"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref();
const visible = ref(false);
</script>格式化日期
formatter 属性可以配置一个接收 CalendarDay 类型的对象,通过此对象可以自定义当前日期展示的内容和样式。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
type="range"
:formatter="formatter"
:current-date="new Date(new Date().getFullYear(), 4, 1)"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import type { CalendarDay } from 'sard-uniapp'
import { ref } from 'vue'
const value = ref<Date>()
const visible = ref(false)
const formatter = (day: CalendarDay) => {
const year = day.date.getFullYear()
const month = day.date.getMonth() + 1
const date = day.date.getDate()
const week = day.date.getDay()
if (month === 5) {
if (date === 1) {
day.bottom = '劳动节'
}
if (date <= 3) {
day.top = '休'
}
if (date === 4) {
day.bottom = '青年节'
}
if (week === 0) {
const weekOnMonthStart = new Date(year, month - 1, 1).getDay()
const secondSunday = 15 - (weekOnMonthStart || 7)
if (secondSunday === date) {
day.bottom = '母亲节'
}
}
}
if (day.type === 'start') {
day.bottom = '入店'
} else if (day.type === 'end') {
day.bottom = '离店'
}
if (week === 0 || week === 6) {
day.style = {
fontWeight: 'bold',
color: 'var(--sar-red)',
}
}
}
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
type="range"
:formatter="formatter"
:current-date="new Date(new Date().getFullYear(), 4, 1)"
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref();
const visible = ref(false);
const formatter = (day) => {
const year = day.date.getFullYear();
const month = day.date.getMonth() + 1;
const date = day.date.getDate();
const week = day.date.getDay();
if (month === 5) {
if (date === 1) {
day.bottom = "\u52B3\u52A8\u8282";
}
if (date <= 3) {
day.top = "\u4F11";
}
if (date === 4) {
day.bottom = "\u9752\u5E74\u8282";
}
if (week === 0) {
const weekOnMonthStart = new Date(year, month - 1, 1).getDay();
const secondSunday = 15 - (weekOnMonthStart || 7);
if (secondSunday === date) {
day.bottom = "\u6BCD\u4EB2\u8282";
}
}
}
if (day.type === "start") {
day.bottom = "\u5165\u5E97";
} else if (day.type === "end") {
day.bottom = "\u79BB\u5E97";
}
if (week === 0 || week === 6) {
day.style = {
fontWeight: "bold",
color: "var(--sar-red)"
};
}
};
</script>展示多个月
默认只展示一个月,如果要表现上下月之间的强关联性,可以设置 severalMonths 属性以展示多个月。 这时设置的最大最小值范围不能太大,避免渲染大量节点造成性能问题。
vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
type="range"
several-months
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const value = ref<Date[]>()
const visible = ref(false)
</script>vue
<template>
<sar-calendar-popout
v-model="value"
v-model:visible="visible"
title="请选择日期"
type="range"
several-months
value-format="YYYY-MM-DD"
/>
<sar-list card>
<sar-list-item
title="请选择日期"
arrow
hover
:value="JSON.stringify(value)"
@click="visible = true"
/>
</sar-list>
</template>
<script setup lang="js">
import { ref } from "vue";
const value = ref();
const visible = ref(false);
</script>API
CalendarPopoutProps
继承 CalendarProps 并有以下额外属性:
| 属性 | 描述 | 类型 | 默认值 |
|---|---|---|---|
| popout-class | 弹窗框根元素类名 | string | - |
| popout-style | 弹窗框根元素样式 | StyleValue | - |
| visible (v-model) | 是否显示弹出框 | boolean | - |
| title | 弹出框标题 | string | - |
| show-confirm | 是否显示确定按钮,隐藏按钮可用于快捷选择 | boolean | true |
| validate-event | 是否触发表单验证 | boolean | true |
| resettable 1.23.3+ | 关闭弹出框后,是否可复位弹出框值 | boolean | false |
CalendarPopoutSlots
| 插槽 | 描述 | 属性 |
|---|---|---|
| title 1.19.2+ | 自定义标题 | - |
| title-prepend 1.19.2+ | 自定义标题前面内容 | - |
CalendarPopoutEmits
| 事件 | 描述 | 类型 |
|---|---|---|
| update:model-value | 日历组件值改变时触发 | (value: Date | Date[] | string | string[] | undefined) => void |
| change | 日历组件值改变时触发 | (value: Date | Date[] | string | string[] | undefined) => void |
| update:visible | 弹出框显隐时触发 | (visible: boolean) => void |
| confirm 1.22.1+ | 点击确定按钮时触发 | () => void |
| visible-hook 1.22.1+ | 入场/退场动画状态改变时触发 | (name: TransitionHookName) => void |
| before-enter 1.22.1+ | 入场动画开始前触发 | () => void |
| enter 1.22.1+ | 入场动画开始时触发 | () => void |
| after-enter 1.22.1+ | 入场动画结束时触发 | () => void |
| enter-cancelled 1.22.1+ | 入场动画取消时触发 | () => void |
| before-leave 1.22.1+ | 退场动画开始前触发 | () => void |
| leave 1.22.1+ | 退场动画开始时触发 | () => void |
| after-leave 1.22.1+ | 退场动画结束时触发 | () => void |
| leave-cancelled 1.22.1+ | 退场动画取消时触发 | () => void |