微信小程序使用日历需要禁用某些日期需求的实现

需求描述:

日历组件,某些日期被人选了,就不能再选,用一个颜色标记。用户可以选择部分能选的。

在这里插入图片描述
类似这样的需求图片。

办法1是,vant-ui 微信小程序插件 本身的日期组件是可以实现的。

具体方法:


    <van-calendar
    title="日历"
    :show="true"
    :formatter="formatter1"
    color="#07c160"
    type="range"
    :show-confirm="false"
/>

我们可以通过`formatter`来自定义渲染内容。

      formatter1(day){
         // 周日全天不可选
        let week = day.date.getDay()
        if(week == 0){
            day.type = 'disabled_yes' // 很牛笔 很关键
        }
          const month = day.date.getMonth() + 1;
      const date = day.date.getDate();

      if (month === 5) {
        if (date === 1) {
          day.topInfo = '劳动节';
        } else if (date === 4) {
          day.topInfo = '五四青年节';
        } else if (date === 11) {
          day.text = '今天';
        }
      }

      if (day.type === 'start') {
        day.bottomInfo = '入住';
      } else if (day.type === 'end') {
        day.bottomInfo = '离店';
      }

        return day
     },

重点: 通过formate函数,我们可以指定日期day.type的类型为disabled 那么,禁用的样式就是官方自己的默认的日期禁用样式。

但是我们需要自定义禁用样式, 那么 day.type = 'day–disabled_yes’设置为一个自定义的名称, vant的组件会自动生成一个 van-calendar__day--disabled_yes的类名,然后 我们通过这个类名 自己写样式就行了。

<style>
.van-calendar__day--disabled_yes {
  color:  red;
}
</style>

最后的效果就是这样子

在这里插入图片描述
但是这种方法有个坑,formate函数,只会在当月执行,其他月份,需要点击月份才能触发,并且担心性能问题。 没有继续研究下去。

方法二:使用wx_calendar这个改写
源码地址:https://github.com/treadpit/wx_calendar
源码文档:https://treadpit.github.io/wx_calendar/v1/guide.html#%E5%BF%AB%E9%80%9F%E6%8E%A5%E5%85%A5

注意: 他有v1 和v2两个版本,方式不一样。 我使用的是v1版本

将src/component/calendar这个目录下的文件全部拷贝到自己的组件目录。

我的是wepy2框架 都可以直接拷贝,原生小程序当然也可以直接用。

文档可以传入我们需要禁用的日期

使用示例demo

<template>
  <div class="container-wrap">
   <calendar calendarConfig="{{calendarConfig}}" />
  </div>
</template>
import wepy from '@wepy/core'

import store from '@/store'

import { disableDay } from '../components/calendar/main.js'
wepy.page({
  store,
  data: {
    calendarConfig: {
      multi: true,
      disableMode: {  // 禁用某一天之前/之后的所有日期
        type: 'before'  // [‘before’, 'after']
        // date: '2020-03-24', // 无该属性或该属性值为假,则默认为当天
      },
      onlyShowCurrentMonth: false
      // defaultDay: '2018-3-6'
    }
  },
  computed: {

  },
  watch: {
  },
  methods: {
    initData() {
      // jump(2018, 6, 6)
      disableDay([
        {
          year: 2021,
          month: '06',
          day: '08',
          class: 'lock'
        },
        {
          year: 2021,
          month: '06',
          day: '27',
          class: 'lock'
        }
      ])
    }
  },
  onLoad() {
    console.log('load')
  },
  onShow() {
    console.log('show')
  },
  onReady() {
    this.initData()
  },
  onHide() {

  }
})
</script>

<config>
{
    navigationBarTitleText: 'demo',
    usingComponents: {
      "calendar": "../components/calendar/index",
      'noData':'../components/noData'
    }
}
</config>

我们传入给组件的禁用日期数据多写了一个class:'lock' 属性,
我们再需要改写一下组件的源码:
calendar/func/day.js

  /**
   * 禁用指定日期
   * @param {array} dates  禁用
   */
  disableDays(dates) {
    const { disableDays = [], days } = this.getData('calendar')
    if (Object.prototype.toString.call(dates) !== '[object Array]') {
      return logger.warn('disableDays 参数为数组')
    }
    let _disableDays = []
    if (dates.length) {
      _disableDays = uniqueArrayByDate(dates.concat(disableDays))
      const disableDaysCol = _disableDays.map(d => getDate.toTimeStr(d))
      // console.log('disableDaysCol', disableDaysCol)
      // console.log('days', days)
      days.forEach(item => {
        const cur = getDate.toTimeStr(item)
        // if (disableDaysCol.includes(cur)) item.disable = true    // 原来的逻辑
        // ++++++ 新增逻辑 sart +++++++
        disableDaysCol.forEach((v, i) => {
          if (cur === v) {
            item.disable = true
            item.class = _disableDays[i].class ? _disableDays[i].class : ''
          }
        })
        // ++++++ 新增逻辑 end +++++++
      })
    } else {
      days.forEach(item => {
        item.disable = false
      })
    }
    this.setData({
      'calendar.days': days,
      'calendar.disableDays': _disableDays
    })
  }

我们把我们想出入的类名就传进去了。并且,会把这个类型渲染到日期上面。

然后我们添加这个自定义样式:

.default_date-disable.lock {
  background-color: red;
}

calendar/func/runder.js

/**
   * 设置日历面板数据
   * @param {number} year 年份
   * @param {number} month  月份
   * @param {number} curDate  日期
   * @param {boolean} disableSelect 是否禁用选中
   */
  calculateDays(year, month, curDate, disableSelect) {
    return new Promise(resolve => {
      // 避免切换日期时样式残影
      this.resetDates()
      let days = []
      const {
        disableDays = [],
        chooseAreaTimestamp = [],
        selectedDay: selectedDates = []
      } = this.getData('calendar')
      days = Day(this.Component).buildDate(year, month)
      let selectedDay = selectedDates
      if (!disableSelect) {
        selectedDay = this.setSelectedDay(year, month, curDate)
      }
      const selectedDayStr = selectedDay.map(d => getDate.toTimeStr(d))
      const disableDaysStr = disableDays.map(d => getDate.toTimeStr(d))
      console.log('disableDaysStr', disableDaysStr)
      const [areaStart, areaEnd] = chooseAreaTimestamp
      days.forEach(item => {
        const cur = getDate.toTimeStr(item)
        const timestamp = getDateTimeStamp(item)
        if (selectedDayStr.includes(cur) && !disableSelect) {
          item.choosed = true
          if (timestamp > areaEnd || timestamp < areaStart) {
            const idx = selectedDay.findIndex(
              selectedDate =>
                getDate.toTimeStr(selectedDate) === getDate.toTimeStr(item)
            )
            selectedDay.splice(idx, 1)
          }
        } else if (
          areaStart &&
          areaEnd &&
          timestamp >= areaStart &&
          timestamp <= areaEnd &&
          !disableSelect
        ) {
          item.choosed = true
          selectedDay.push(item)
        }
        // if (disableDaysStr.includes(cur)) item.disable = true  // 原来的逻辑
        // ++++++ 新增逻辑 sart +++++++
        disableDaysStr.forEach((v, i) => {
          if (cur === v) {
            item.disable = true
            item.class = disableDays[i].class ? disableDays[i].class : ''
          }
        })
 		// ++++++ 新增逻辑 end +++++++
        const {
          disableDateTimestamp,
          disableType
        } = this.__getDisableDateTimestamp()
        let disabelByConfig = false
        if (disableDateTimestamp) {
          if (
            (disableType === 'before' && timestamp < disableDateTimestamp) ||
            (disableType === 'after' && timestamp > disableDateTimestamp)
          ) {
            disabelByConfig = true
          }
        }
        const isDisable = disabelByConfig || this.__isDisable(timestamp)
        if (isDisable) {
          item.disable = true
          item.choosed = false
        }
      })
      this.setData(
        {
          'calendar.days': days,
          'calendar.selectedDay': [...selectedDay] || []
        },
        () => {
          resolve()
        }
      )
    })
  }

最终的显示效果如下:
在这里插入图片描述
红色就是我们传入的需要禁用的。灰色背景的,就是插件默认的禁用样式。

整个组件的样式都是可以自定义修改的,具体就查看组件内的样式文件。

使用calendar v2版本实现以上需求

第一步:把源码src/component/v2目录下的文件全部拷贝到自己的组件文件夹下,我的是src/components/calendar2

第二步:安装官方文档说的开干

<style lang="less">
.default_date-disable.lock {
  background-color: red;
}
// 自定义样式
.orange-date {
  background-color: rgb(248, 238, 147);
}
</style>
<template>
  <div class="container-wrap">
    <p>日历插件1</p>
   <calendar calendarConfig="{{calendarConfig}}" />
   <p>日历插件2</p>
   <calendar2 id="calendar" config="{{calendarConfig2}}" />
  </div>
</template>

<script>
import wepy from '@wepy/core'

import store from '@/store'

import { disableDay } from '../components/calendar/main.js'
import plugin from '../components/calendar2/plugins/index.js'
import selectable from '../components/calendar2/plugins/selectable.js'
plugin.use(selectable) // 安装日期组件的插件
wepy.page({
  store,
  data: {
    calendarConfig: {
      multi: true,
      disableMode: {  // 禁用某一天之前/之后的所有日期
        type: 'before'  // [‘before’, 'after']
        // date: '2020-03-24', // 无该属性或该属性值为假,则默认为当天
      },
      onlyShowCurrentMonth: false
      // defaultDay: '2018-3-6'
    },
    calendarConfig2: {
      multi: true,
      // theme: 'elegant',
      // hideHeader: true,
      emphasisWeek: false,
      chooseAreaMode: false,
      disableMode: {  // 禁用某一天之前/之后的所有日期
        type: 'before'  // [‘before’, 'after']
      }
    }
  },
  computed: {

  },
  watch: {
  },
  created() {
    console.log('created')
    // const calendar = this.$app.selectComponent('#calendar').calendar
    // console.log('calendar', calendar)
  },
  mounted() {
    console.log('mounted')
  },
  methods: {
    initData() {
     // const pages = getCurrentPages()
      // const currentPage = pages[pages.length - 1]
      // console.log('this.calendar', currentPage)
      // console.log('this.calendar', jump)
      // jump(2018, 6, 6)
      disableDay([
        {
          year: 2021,
          month: '06',
          day: '08',
          lock: true,
          class: 'lock'
        },
        {
          year: 2021,
          month: '06',
          day: '27',
          lock: true,
          class: 'lock'
        }
      ])
    }
  },
  onPullDownRefresh: function () {
        // 调用刷新时将执行的方法
    console.log('下拉刷新')
  },
  onReachBottom() {
    // console.log('上拉加载')

  },
  onPageScroll: function(e) {
  },
  onLoad() {
    console.log('load')
  },
  onShow() {
    console.log('show')
  },
  onReady() {
    console.log('ready')
    this.initData()
    const toSet = [
      {
        year: 2021,
        month: 7,
        date: 15
      },
      {
        year: 2021,
        month: 7,
        date: 18
      }
    ]
    const calendar = this.$wx.selectComponent('#calendar').calendar
    calendar.setSelectedDates(toSet)
    const toDis = [
      {
        year: 2021,
        month: 7,
        date: 12,
        class: 'orange-date'
      },
      {
        year: 2021,
        month: 7,
        date: 13,
        class: 'orange-date'
      },
      {
        year: 2021,
        month: 7,
        date: 14,
        class: 'orange-date'
      }
    ]
    // 设置禁用日期
    calendar.disableDates(['2021-7-12', '2021-7-13', '2021-7-14'])
    // 设置自定义日期样式
    calendar.setDateStyle(toDis)
    // calendar.jump({year: 2018, month: 6, date: 6})
  },
  onHide() {

  }
})
</script>

<config>
{
    navigationBarTitleText: 'demo',
    usingComponents: {
      "calendar": "../components/calendar/index",
       "calendar2": "../components/calendar2/index",
    }
}
</config>

v2版本的,我们就不需要手动去改源码了。因为,v2版本插件,提供了一个设置指定日期样式的方法calendar.setDateStyle(toSet)
所以,我们可以传入自定义的样式类名进去就行了。

注意:v2版本 官方有问题,有bug ,走不通。 最后方案还是用的v1实现的。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值