The secondary encapsulation of the vant calendar selector component in vue; the main functions are as follows:
The main function:
- date range selection (basic);
- Customize the bottom button of the selector, add a clear time operation (slot slot);
- Specify the date range selected by default (current date to the end of this month via default-date)
- Custom date optional range; (via min-date and max-date)
- Support the import of default values; (placeholder will be displayed when there is no default value: please select a time interval)
- Customize the width of the component; (through props:Width, it is recommended to use a percentage such as: 80%)
The renderings are as follows:
The date interval component is implemented as follows: calendar.vue
Main code explanation:
1. By
<template slot="footer">
changing the default button at the bottom, I added a清除时间
button here; clicking清除时间
the button will clear the time and restore it to the default state;
2. Bymin-date 和 max-date
controlling the range of the start and end of the date;
3. Throughdefault-date
the Change the date range specified by default. It should be noted that the return is an array, the start position and the end position; you can take a look at the timeInterval() method; 4. Click the confirm button onConfirmAll() to return the selected start date
and end date To the parent component; the time format is as follows:2023-02-20
;
5, you can pass in the defaultData default value, if there is no default value, it will be displayed:请选择时间区间
;
6, you can pass in:Width="'100%'"
to control the width of the component;
7, you can make corresponding changes to the current component according to different business needs adjustment;
<template>
<!-- 日期选择组件 可指定选择范围 -->
<div class="calendar" :style="`width:${Width}`">
<van-field :label="title" v-model="date" right-icon="arrow-down" readonly @click="show = true" :placeholder="placeholder" />
<!-- 日期选择器 -->
<van-calendar safe-area-inset-bottom v-model="show" color="#1989fa" type="range" @confirm="onConfirm" :min-date="minDate" :max-date="maxDate" :default-date="timeInterval()" ref="myCalendar">
<template slot="footer">
<div class="footer">
<van-button @click="clearTimeAll" type="danger" class="footerBtn">清除时间</van-button>
<van-button class="footerBtn" @click="onConfirmAll" type="info">确认</van-button>
</div>
</template>
</van-calendar>
</div>
</template>
<script>
export default {
name: 'calendar',
components: {
},
props: {
/* 可以不用传 用来展示左侧的文案 为空则不展示文案*/
title: {
type: String,
default: '',
},
/* 传过来的默认值 */
defaultData: {
type: String,
// default:'请选择'
},
placeholder: {
type: String,
default: '请选择时间区间',
},
// 宽度
Width: {
type: String,
},
},
data() {
return {
date: this.defaultData ? this.defaultData : '', // 先判断有没有默认值 有就用没有就为空
show: false,
// 日期区间
minDate: new Date(2022, 0, 1),
maxDate: new Date(2025, 12, 31),
// 当前日期
currentDate: new Date().getDate(),
};
},
computed: {
},
watch: {
// 监听到需要重新赋值
defaultData(newValue) {
this.date = newValue;
},
},
created() {
// 处理默认值 如果有默认值直接赋值
if (this.defaultData) {
this.date = this.defaultData;
}
},
mounted() {
},
methods: {
/* 日期区间 当前自动选择的日期区间 :取当天到月底 返回的是一个数组*/
timeInterval() {
let new_year = new Date().getFullYear();
let new_month = new Date().getMonth() + 1;
let new_date = new Date(new_year, new_month, 1); //取当年当月中的第一天
let end = new Date(new_date.getTime() - 1000 * 60 * 60 * 24); //取最后一天
return [new Date(), end];
},
/* 确认选择 组件自带的事件 */
onConfirm(date) {
const [start, end] = date;
this.show = false;
this.date = `${
this.formatDate(start)} - ${
this.formatDate(end)}`;
// 传给父组件 以此来请求数据
this.$emit('dateFun', `${
this.formatDate(start)}`, `${
this.formatDate(end)}`);
},
/* 确认按钮 */
onConfirmAll() {
// 直接调用上面的方法
if (this.$refs.myCalendar) {
this.$refs.myCalendar.onConfirm();
} else {
console.warn('myCalendar实例没有获取到');
}
},
/* 清除时间 时间置空*/
clearTimeAll() {
this.date = '';
this.show = false;
this.$emit('dateFun', ``, ``);
},
/* 转换时间 */
formatDate(date) {
// 给日期补0
return `${
date.getFullYear()}-${
(date.getMonth() + 1).toString().padStart(2, '0')}-${
date.getDate().toString().padStart(2, '0')}`;
},
},
};
</script>
<style scoped lang="scss">
// 覆盖 van-field的样式
/deep/ .van-cell {
padding: 2px 5px;
border-radius: 5px;
border: 1px solid #1457f0;
}
/deep/ .van-field__right-icon {
margin-right: 0;
padding: 0;
color: #1457f0;
}
.footer {
display: flex;
justify-content: space-between;
align-items: center;
// 底部自定义按钮的样式
.footerBtn {
width: 150px;
border-radius: 2px;
}
}
</style>
In the parent component use:
<template>
<div>
<!-- 日期区间选择器演示 -->
<h4>Vant日期区间选择器封装</h4>
<div class="Calendar">
<Calendar @dateFun="dateFun" :Width="'80%'" :defaultData="defaultData"></Calendar>
</div>
</div>
</template>
<script>
// 时间选择器
import Calendar from '../../components/calendar/calendar.vue';
export default {
//注册
components: {
Calendar },
data() {
return {
// 组件的默认值 没有可以为空 或者 组件中不在使用defaultData属性
defaultData:'2023-01-01-2023-02-01',
],
};
},
methods: {
//接收子组件传过来的日期值
dateFun(start, end) {
console.log('start:', start, 'end:', end);
// 保存获取到的时间...
},
},
};
</script>
<style scoped lang="scss">
.Calendar {
margin-top: 20px;
}
</style>