基于Vant UI框架实现时间段选择器

2 篇文章 0 订阅
1 篇文章 0 订阅

组件代码如下:

<template>
    <van-picker
            :title="title"
            :show-toolbar="showToolbar"
            :columns="columns"
            @confirm="onConfirm"
            @cancel="onCancel"
            @change="onChange"
            :confirm-button-text="confirmButtonText"
            :cancel-button-text="cancelButtonText"
            :loading="loading"
            :readonly="readonly"
            :item-height="itemHeight"
            :visible-item-count="visibleItemCount"
            :swipe-duration="swipeDuration"
    >
       <template slot="default">
           <slot name="default"></slot>
       </template>
        <template slot="title">
            <slot name="title"></slot>
        </template>
        <template slot="confirm">
            <slot name="confirm"></slot>
        </template>
        <template slot="cancel">
            <slot name="cancel"></slot>
        </template>
        <template slot="option">
            <slot name="option"></slot>
        </template>
        <template slot="columns-top">
            <slot name="columns-top"></slot>
        </template>
        <template slot="columns-bottom">
            <slot name="columns-bottom"></slot>
        </template>
    </van-picker>
</template>

<script>
    import Vue from 'vue'
    import { Field, Picker, Popup } from 'vant';
    Vue.use(Field).use(Picker).use(Popup);

    export default {
        name: "VanDatePicker",
        props: {
            value: {
                type: Date,
                default: () => new Date()
            },
            minDate: {
                type: Date,
                default: () => new Date(new Date().getFullYear()-5,0,1)
            },
            maxDate: {
                type: Date,
                default: () => new Date(new Date().getFullYear()+5,0,1)
            },
            showToolbar: {
                type: Boolean,
                default: () => false
            },
            title: {
                type: String,
                default: () => ''
            },
            confirmButtonText: {
                type: String,
                default: () => '确认'
            },
            cancelButtonText: {
                type: String,
                default: () => '取消'
            },
            loading: {
                type: Boolean,
                default: () => false
            },
            readonly: {
                type: Boolean,
                default: () => false
            },
            itemHeight: {
                type: Number||String,
                default: () => 44
            },
            visibleItemCount: {
                type: Number||String,
                default: () => 6
            },
            swipeDuration: {
                type: Number||String,
                default: () => 1000
            },
        },
        data() {
            return {
                monthArr: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'],
                dayArr: ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12','13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24','25', '26', '27', '28', '29', '30', '31'],
            };
        },
        
        computed: {
            columns: function () {
                let minYear = this.minDate.getFullYear();
                let maxYear = this.maxDate.getFullYear();
                let year = this.value.getFullYear();
                let month = this.value.getMonth();
                let day = this.value.getDate();
                let yearArr = [];
                let i = 0;
                while (i < maxYear - minYear + 1) {
                    yearArr.unshift((maxYear - i) + '');
                    i ++;
                }
                let columns = [
                    {
                        values: yearArr,
                        defaultIndex: Math.floor(year) - minYear
                    },
                    {
                        values: this.monthArr,
                        defaultIndex: Math.floor(month)
                    },
                    {
                        values: this.dayArr,
                        defaultIndex: Math.floor(day-1)
                    },
                    {
                        values: ['-']
                    },
                    {
                        values: yearArr,
                        defaultIndex: Math.floor(year) - minYear
                    },
                    {
                        values: this.monthArr,
                        defaultIndex: Math.floor(month)
                    },
                    {
                        values: this.dayArr,
                        defaultIndex: Math.floor(day-1)
                    },
                ];
                return columns
            }
        },

        watch: {

        },
        
        methods: {
            onConfirm(value, index) {
                // console.log(`当前值:${value}, 当前索引:${index}`);
                this.$emit('confirm',value,index);
            },
            onChange(picker, value, index) {
                // console.log(`当前值:${value}, 当前索引:${index}`);
                let _this = this;

                let minMonth = this.minDate.getMonth();
                let minDay = this.minDate.getDate();
                let maxMonth = this.maxDate.getMonth();
                let maxDay = this.maxDate.getDate();
                let d = new Date(value[0],value[1],0);

                setDate(0);
                setDate(4);
                function setDate(i) {
                    //最小年份
                    if (value[i]-0===_this.minDate.getFullYear()) {
                        picker.setColumnValues(i+1,_this.monthArr.slice(minMonth));
                        let strMinM = '';
                        if (minMonth<9) {
                            strMinM = '0'+(minMonth+1)
                        } else {
                            strMinM = strMinM + 1 + ''
                        }
                        picker.setColumnValue(i+1,value[i+1]-1<minMonth?strMinM:value[i+1]);

                        if (index===i&&value[i+1]-1<minMonth) {
                            picker.setColumnValues(i+2,_this.dayArr.slice(minDay-1,d.getDate()));
                            picker.setColumnValue(i+2,value[i+2]<minDay?minDay.toString():value[i+2]);
                        } else {
                            if (value[i+1]-1===_this.minDate.getMonth()) {
                                picker.setColumnValues(i+2,_this.dayArr.slice(minDay-1,d.getDate()));
                                picker.setColumnValue(i+2,value[i+2]<minDay?minDay.toString():value[i+2]);
                            } else {
                                picker.setColumnValues(i+2,_this.dayArr.slice(0,d.getDate()));
                                picker.setColumnValue(i+2,value[i+2]>d.getDate()?d.getDate().toString():value[i+2]);
                            }
                        }
                    }
                    //最大年份
                    else if (value[i]-0===_this.maxDate.getFullYear()) {
                        picker.setColumnValues(i+1,_this.monthArr.slice(0,maxMonth+1));
                        let strManM = '';
                        if (maxMonth<9) {
                            strManM = '0'+(maxMonth+1)
                        } else {
                            strManM = maxMonth + 1 + ''
                        }
                        picker.setColumnValue(i+1,value[i+1]-1>maxMonth?strManM:value[i+1]);
                        if (index===i&&value[i+1]-1>maxMonth) {
                            picker.setColumnValues(i+2,_this.dayArr.slice(0,maxDay));
                            picker.setColumnValue(i+2,value[i+2]>maxDay?maxDay.toString():value[i+2]);
                        } else {
                            if (value[i+1]-1===_this.maxDate.getMonth()) {
                                picker.setColumnValues(i+2,_this.dayArr.slice(0,maxDay));
                                picker.setColumnValue(i+2,value[i+2]>maxDay?maxDay.toString():value[i+2]);
                            } else {
                                picker.setColumnValues(i+2,_this.dayArr.slice(0,d.getDate()));
                                picker.setColumnValue(i+2,value[i+2]>d.getDate()?d.getDate().toString():value[i+2]);
                            }
                        }
                    }
                    //其他年份
                    else {
                        picker.setColumnValues(i+1,_this.monthArr);
                        picker.setColumnValue(i+1,value[i+1]);
                        picker.setColumnValues(i+2,_this.dayArr.slice(0,d.getDate()));
                        picker.setColumnValue(i+2,value[i+2]>d.getDate()?d.getDate().toString():value[i+2]);
                    }
                }

                let finallyVal = picker.getValues();
                let len = Math.floor(finallyVal.length/2);
                //开始时间不大于结束时间
                if (finallyVal.slice(0,len).join("")>finallyVal.slice(len+1).join("")){
                    picker.setValues([...finallyVal.slice(0,len),"-",...finallyVal.slice(0,len)]);
                    if (new Date(finallyVal.slice(0,len).join("-")+' 00:00:00').getTime()===this.maxDate.getTime()) {
                        console.log(111);
                        picker.setColumnValues(5,_this.monthArr.slice(0,maxMonth+1));
                        picker.setColumnValues(6,_this.dayArr.slice(0,maxDay));
                    }
                }

                this.$emit('change',picker,finallyVal,index);
            },
            onCancel() {
                // console.log('取消');
                this.$emit('cancel');
            },
        },
    }
</script>

<style scoped>

</style>

调用demo

<template>
    <div>
        <van-field
                readonly
                clickable
                label="时间段"
                :value="value"
                placeholder="选择时间段"
                @click="showPicker = true"
        />
        <van-popup v-model="showPicker" round position="bottom">
            <van-date-picker
                    show-toolbar
                    v-model="currentDate"
					title="选择时间段"
                    :min-date="minDate"
                    :max-date="maxDate"
                    @cancel="showPicker = false"
                    @confirm="onConfirm"
                    @change="onChange"
            >
            </van-date-picker>
        </van-popup>
    </div>
</template>

<script>
    import VanDatePicker from '@/components/VanDatePicker';

    export default {
        name: "Test",
        components: {VanDatePicker},
        data() {
            return {
                value: '',
                showPicker: false,
                minDate: new Date(2010, 5, 15),
                maxDate: new Date(2025, 10, 15),
                currentDate: new Date(),
                startDate: '',
                endDate: '',
            };
        },

        mounted() {

        },

        methods: {
            onConfirm(value, index) {
                console.log(`当前值:${value}, 当前索引:${index}`);
                this.startDate = value.slice(0,3).join('-');
                this.endDate = value.slice(4,7).join('-');
                this.value = this.startDate + '至' + this.endDate;
                this.showPicker = false
            },

            onChange(picker, value, index) {
                console.log(`当前值:${value}, 当前索引:${index}`);
            },
        },
    }
</script>

<style scoped>

</style>

UI示例
在这里插入图片描述
API:注意红色划掉的没有实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
引用中提到,vantUI的时间选择器是通过在弹出层中放置选择器实现的,通过v-if控制显示与隐藏。 而引用中指出,vantUI的时间选择器提供了cancel和confirm两个事件,点击取消或确认按钮会触发相应事件,其中confirm事件的回调参数value表示当前选择的时间。 根据引用中的代码,可以看出vantUI的时间选择器默认选中值为当前日期,而且可以通过change事件来监听选择的时间的变化。 在代码中,通过Change()方法可以获取当前选择的时间,并将其进行格式化,最终得到一个形如"年-月-日 时:分:秒"的时间字符串。 总结起来,vantUI的时间选择器可以通过弹出层的方式进行选择,并提供了cancel和confirm事件来处理用户的取消或确认操作,同时可以监听时间的变化并进行相应的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [VantUI时间选择器](https://blog.csdn.net/qq_46003166/article/details/105169582)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [vantUI时间选择器将选中值改为 yyyy-mm-dd 00:00:00 格式](https://blog.csdn.net/lwfcomeon/article/details/86677450)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值