vue 的日期控件 简单实现

使用的是 vue 2.2.1 版本,暂时只支持 input框 

<template>
    <transition name="DTpicker">
    <div id="DTpicker" class="DTpicker" v-show="isShow">
        <div class="DTpicker_t">
            <p>{{ monthList[month -1] }}&nbsp;&nbsp;{{ year }}</p>
            <span class="DTpicker_t_l" @click="changeMonth(-1)"> &lsaquo; </span>
            <span class="DTpicker_t_r"  @click="changeMonth(1)"> &rsaquo; </span>
        </div>
        <table class="DTpicker_m">
            <thead>
                <tr key="thead">
                    <th v-for="w in weekList" :key="w">{{w}}</th>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(d,index) in da" :key="index">
                    <td
                    :class="{'gray': day.sign == 0 || day.sign == 2,'current' : day.day == currentDay && day.sign !== 0 && day.sign !== 2}"
                    v-for="day in d"
                    @click="changeDay(day)"
                    :key="day.sign +'-' + day.day"
                    >{{day.day}}</td>
                </tr>
            </tbody>
        </table>
    </div>
    </transition>
</template>
<script>
export default {
    data(){
        return {
            weekList:['Su','Mo','Tu','We','Th','Fr','Sa'],
            monthList:['January','February','March','April','May','June','July','August','September','October','November','December'],
            // monthList:[1,2,3,4,5,6,7,8,9,10,11,12],
            month:0,
            year:0,
            week:'',
            currentDay:0,
            listArr:[],
            isShow:false,
            timerId:null,
            isFocus:false,
            isMouseover:false,
        }
    },
    props:{
        el: {
          type: String,
          default: ''
        },
    },
    computed:{
        da(){  // 设置数据格式
            var arr = [];
            if(this.listArr.length <= 0) return arr;
            for(var i =0;i*7<this.listArr.length;i++){
                arr.push(this.listArr.slice(i*7,(i+1)*7));
            }
            return arr;
        },

        timeFormat(){
            return this.year+ '-' + this.month + '-' + this.currentDay
        }
    },
    methods:{
        getCountDays(timeFormat) {
            var arr = timeFormat.split('-');
            var date = new Date(Number(arr[0]),Number(arr[1]),0);
           return date.getDate();  //返回某月天数
        },
        getUpDay(date){
            var arr = date.split('-'),timeFormat;
            if(arr[1] == 1){
              timeFormat = arr[0] -1 + '-' + 12 + '-' + 1;
            }else {
               timeFormat = arr[0] + '-' + (arr[1] - 1) + '-' + 1;
            }
            return this.getCountDays(timeFormat);    //返回上个月的天数
        },
        getNextDay(date){
            var arr = date.split('-'),timeFormat;

            if(arr[1] == 12){
              timeFormat = Number(arr[0]) + 1 + '-' + 1 + '-' + 1;
            }else {
               timeFormat = arr[0] + '-' + (Number(arr[1]) + 1) + '-' + 1;
            }
            return this.getCountDays(timeFormat);  //返回下个月的天数
        },
        dateArr(date){   //设置listArr
            var listArr=[];
            var startDay = this.getUpDay(date);
            var endDay = this.getNextDay(date);
            var cDate =this.getCountDays(date);
            var startWeek = new Date(this.year+ '-' + this.month + '-' + 1).getDay();
            var endWeek = new Date(this.year+ '-' + this.month + '-' + cDate).getDay();
            for(var i = 1;i<=cDate;i++){
                listArr.push({
                    day:i,
                    sign:1
                });
            }
            if(startWeek != 0){
                for (var i = startDay; i >startDay - startWeek; i--) {
                    listArr.unshift({
                        day:i,
                        sign:0

                    });
                };
            }
            if(endWeek != 6){
                for (var i = 1; i <= 6 - endWeek ; i++) {
                    listArr.push({
                        day:i,
                        sign:2
                    });
                };
            }
            if(i >5){
                i=0;
            }
            if(listArr.length <= 35){
                for(var j =0; j<7;j++){
                    listArr.push({
                        day:i+j,
                        sign:2
                    });
                }
            }
            this.listArr = listArr;
        },
        setYMD(date){   //设置年月日
            date = date || new Date() ;
            this.year = date.getFullYear();
            this.month = date.getMonth() + 1;
            this.currentDay = date.getDate();
        },
        changeMonth(num){   // 改变月份
            var  timeFormat;
            if(this.month <=1 && num <0){
                timeFormat = this.year-1 + '-' + 12 + '-' + this.currentDay
            }else if(this.month >=12 && num >0){
                timeFormat = this.year + 1 + '-' + 1 + '-' + this.currentDay
            }else{
                timeFormat =this.year+ '-' + ( this.month + num ) + '-' + this.currentDay
            }
            this.setYMD(new Date(timeFormat));
            this.dateArr(timeFormat);
            this.$emit('changeDay',this.timeFormat)
        },
        changeDay(data){
            console.log(data)
            if(data.sign == 0){
                if(this.month <=1){
                    this.year -=1;
                    this.month = 12;
                }else {
                    this.month -= 1;
                }
            }else if(data.sign == 2){
                if(this.month >=12){
                    this.year +=1;
                    this.month = 1;
                }else {
                    this.month += 1;
                }
            }
            this.currentDay = data.day;
            this.dateArr(this.year+ '-' + this.month + '-' + this.currentDay);
            this.$emit('changeDay',this.timeFormat)
        },
        position(){  // 设置位置 以及绑定事件
            var _this = this;
            if(this.el == '') return ;
            var el = document.querySelector(this.el);
            if(el == null) return;
            var dTpicker = document.querySelector('#DTpicker');
            var obj = getAbsPoint(el);
            var t = obj.y,
                l = obj.x,
                w = el.offsetWidth,
                h = el.offsetHeight,
                bw = document.documentElement.clientWidth || document.body.clientWidth,
                bh =document.body.scrollHeight || document.documentElement.scrollHeight;
            if(bw - l < 260){
                dTpicker.style.right = 0;
            }else {
                console.log(1);
                dTpicker.style.left = l + 'px';
            }
            if(bh - t -h <265){
                console.log(bh,'bh')
                console.log(t)
                dTpicker.style.bottom = bh - t + 5 + 'px';
            }else {
                dTpicker.style.top = t + h + 5 + 'px';
            }
            el.addEventListener('focus',focusEvent);
            el.addEventListener('blur',blurEvent);
            dTpicker.addEventListener('mouseenter', mouseenterEvent )
            dTpicker.addEventListener('mouseleave', mouseleaveEvent )
            function focusEvent(){
                clearTimeout(_this.timerId)
                _this.isFocus = true;
                _this.isShow = true;
            }
            function blurEvent(){
                _this.isFocus = false;
                hide()
            }
            function mouseenterEvent(){
                clearTimeout(_this.timerId)
                _this.isMouseover = true;
            }
            function mouseleaveEvent(){
                _this.isMouseover = false;
                hide()
            }
            function hide(){
                if(_this.isFocus == false && _this.isMouseover == false){
                    _this.timerId = setTimeout(function(){
                        _this.isShow = false;
                    },500)
                }

            }
            function getAbsPoint(e){ // 获取距离左右两侧的位置
                    var x = e.offsetLeft;
                    var y = e.offsetTop;
                    while(e = e.offsetParent)
                    {
                        x += e.offsetLeft;
                        y += e.offsetTop;
                    }
                    return {'x': x, 'y': y};
            };
        }

    },
    created(){
        this.setYMD();
        this.dateArr(this.year+ '-' + this.month + this.currentDay);
    },
    mounted(){
        this.position();
    }
}
</script>
<style scoped lang="scss">
    #DTpicker {
        border: 1px solid #ccc;
        position: absolute;
        box-sizing:border-box;
        font-size: 12px;
        width: 260px;
        z-index: 999;
        position: absolute;
        padding: 5px;
        .DTpicker_t {
            line-height: 34px;
            text-align: center;
            position: relative;
            background-color: #41a9cc;
            font-weight: 700;
            color:#fff;
            span {
                font-size: 20px;
                line-height: 34px;
            }
            .DTpicker_t_l {
                position: absolute;
                top: 0;
                left: 0px;
                width: 30px;
                cursor:pointer;
            }
            .DTpicker_t_r {
                position: absolute;
                top: 0;
                right: 0px;
                width: 30px;
                cursor:pointer;
            }
        }
        .DTpicker_m {
            .gray {
                color:#ccc;
            }
        }
        th,td {
            width: 36px;
            height: 30px;
            line-height: 30px;
            text-align: center;
        }
        td {
            cursor:pointer;
        }
        td.current {
            background-color: #41a9cc;
        }
    }
    /* 设置过渡 */
    .DTpicker-enter-active, .DTpicker-leave-active {
      transition: opacity .5s
    }
    .DTpicker-enter, .DTpicker-leave-active {
      opacity: 0
    }
</style>

使用方法有点麻烦,下面是个例子

<template>
    <div>
        <input type="text" v-model="time" id="date">
        <!-- time 用于接收时间(string) 返回的格式是 YYYY-MM-HH -->
        <com @changeDay="getDate" el="#date"></com>
       <!--  @changeDay="getDate"  用于监听子组件中的事件 名字貌似写死了
        el="#date" 用于向子组件传值 -->
    </div>
</template>
<script>
import com from './DTpicker.vue'
export default {
    data(){
        return {
            time:'',  //返回的格式是 YYYY-MM-HH
        }
    },
    components:{
        com
    },
    methods:{
        getDate(timeFormat){  //用于监听子组件中的事件
            this.time = timeFormat;
        }
    }
}
</script>

 

转载于:https://www.cnblogs.com/yiyuanxia/p/6802083.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值