需求背景

在Vant 的日历组件中想要禁用某些指定的日期,但是Vant 并没有提供类型disabledDate这样的的选项给我们配置。

通过阅读Vant 的 calendar组件源码,可以发现当这个日期的 type 属性值为 disabled时,就会禁用当前日期。

我们可以通过formatter这个属性来重新定义每一个日期的数据。从而改变 type的属性值。

实现方法

示例:所有的周日都不可选

<van-calendar
    title="日历"
    :min-date="minDate"
    :max-date="maxDate"
    :poppable="false"
    :formatter="formatter"
    :show-confirm="false"
    :style="{ height: '380px' }"
/>
methods:{
    formatter(day){
        /*
            这里的参数包含以下属性
            bottomInfo: undefined
            date: Sat May 22 2021 00:00:00 GMT+0800 (中国标准时间) {}
            text: 22
            type: "

            我们只需要修改type值为 disabled 即可
        */

        // 周日全天不可选
        let week = day.date.getDay()
        if(week == 0){
            day.type = 'disabled'
        }
        return day
    }
}

原理分析

如果 type === 'disabled' 则当前日期禁用

// 生成单个日期
genDay: function genDay(item, index) {
    // ...
    var disabled = type === 'disabled';

    var onClick = function onClick() {
        if (!disabled) {
            _this2.$emit('click', item);
        }
    };
    // ...
}

我们可以发现每个日期是通过 days 遍历生成的。

genDays: function genDays() {
    var h = this.$createElement;
    var days = this.shouldRender ? this.days : this.placeholders;
    return h("div", {
    "ref": "days",
    "attrs": {
        "role": "grid"
    },
    "class": (0, _utils2.bem)('days')
    }, [this.genMark(), days.map(this.genDay)]);
},

days 这个数据是一个计算属性,如果选项中有formatter属性,就会调用,所以我们可以在 formatter 中做我们想要的。

days: function days() {
    var days = [];
    var year = this.date.getFullYear();
    var month = this.date.getMonth();

    for (var day = 1; day <= this.totalDay; day++) {
        var date = new Date(year, month, day);
        var type = this.getDayType(date);
        var config = {
            date: date,
            type: type,
            text: day,
            bottomInfo: this.getBottomInfo(type)
        };

        if (this.formatter) {
            config = this.formatter(config);
        }

        days.push(config);
    }

    return days;
}