vue 基于ele创建一个自定义日历

845 阅读3分钟

参照官方的文档 自己简单制作出了一个基本样式的日历

image.png

image.png

在日历组件上方 再引用别的饿了么组件 创建两个下拉框 选项 一个选择年份 一个选择月份

需求:

  1. 上方下拉框的值 与日历的日期对应的年月双向绑定
  2. 获取日历中的时间 将双休日的区域内 加上 '休' 字
  3. 将2022.4.5 的日期内添加上 清明节的文字

步骤一

// 首先给 两个下拉框 以及日历 使用 v-model 分别绑定相应的值 year,month,value 
// 在script 中的 data 函数内 返回 三个变量 分别取上最新的时间
// value: new Date(),year: new Date().getFullYear(),month: new Date().getMonth()
// 给年设置一个数组 option  根据今年的年份 创建一个 2017-2027 的数组
data() { 
  return {
      value: new Date(),
      options: [2021, 2022, 2023], 
      year: new Date().getFullYear(),
      month: new Date().getMonth() + 1
}

步骤二

// 打开网页后 在created钩子函数里面 创建一个11 的伪数组 然后转化成真数组 然后遍历这个数组
// 根据每一项的下标  在今年的年份减去5的基础上 循环和其相加  然后给这个数组每一项赋值对应的年份
created() { 
   /* 如何将伪数组转换成真数组 */ 
   // console.log([...Array(11)]); 
   // console.log(Array.from(Array(11))); 
   var arr = Array.from(Array(11)) 
   arr.forEach((item, index) => { 
       // console.log(item + index, 99);
       // console.log(index - 5 + 2022, 99); 
       // item = index - 5 + 2022; 
       arr[index] = index - 5 + this.year 
   })
   this.options = arr 
   // 得到的数组为 [2017,2018,...,2027]
}

步骤三

// 给两个下拉框绑定一样的 change事件  改变里面的之后 将日历绑定的value值的 日期重新赋值 实现下拉框控制日历
// 赋值为 改变后的 年份和月份的拼接
changeHandle() {
      // 这里实现了下拉框 控制 日历内容功能
      this.value = `${this.year}-${this.month}`
      // console.log(this.value, 999)
}

步骤四

// 点击日历框里面的一个日期,然后在updated钩子函数里面获取到最新的日期(此时点击的日期)
// 将此时的日期使用getFullYear 和 getMonth 方法获取年月 赋值给下拉框里面绑定的year和month
// 这样就完成了下方日历事件更换控制上方下拉框里面的值的变化同步
updated() {
    // 这里获取了更新后的新日期
    // console.log(this.value, 777777777777777)
    // console.log(new Date(this.value), 666666666)
    // console.log(new Date(this.value).getFullYear(), 77777777)
    // console.log(new Date(this.value).getMonth() + 1, 88888888)
    // 上下时间绑定
    // 调用 getFullYear方法 需要前面的时间的格式符合标准
    this.year = new Date(this.value).getFullYear()
    this.month = new Date(this.value).getMonth() + 1
}

步骤五

// 根据日历组件的文档 里面的dateCell scoped slot参数 为 date(单元格代表的日期) 和 data 两种
// 这里使用date参数 使用new Date(date).getDate() 获取每个格子里面对应的日期
<el-calendar v-model="value">
      <template
        slot="dateCell"
        slot-scope="{ date }"
      >
        {{ new Date(date).getDate() }}
        <!-- 这里加载出的每个日期最外层是一个盒子  这里设置的什么标签  盒子里面就是什么标签 -->
        <span v-if="getDay(date)" style="background: red; color: #fff"></span>
        <p v-if="checkDay(date)" style="color: skyblue">清明</p>
      </template>
</el-calendar>

步骤六

// 对日历组件中的周六周日附加上 '休' 字 
// 放入span标签 附加相应的属性 使用v-if 来控制是否有 '休' 字  v-if绑定getDay()方法 里面传值这里的 date
// 将传入的日期取到对应的 星期 如果是星期六或者星期日 就返回true 否则false
getDay(t) {
      //  在 scoped-slot 可以获取到 date(当前单元格的日期)
      // console.log(t, 888888)
      const day = t.getDay()
      if (day === 6 || day === 0) {
        return true
      } else {
        return false
      }
      // console.log(day, 7777777)
}

// 对日历组件中的2022.4.5附加上 '清明' 两字 
// 放入 p标签 里面也加上对应自定义css 同样使用v-if控制有无  v-if绑定 checkDay方法 传值同上date
// 将传入的日期年月日拿到 然后判断是否是 2022.4.5 返回 true 或者 false
checkDay(t) {
      const y = t.getFullYear()
      const m = t.getMonth() + 1
      const d = t.getDate()
      console.log(y, m, d, 666666)
      if (y === 2022 && m === 4 && d === 5) {
        return true
      }
      return false
}

完整代码如下:

<template>
  <div>
    <div>
      <el-select v-model="year" placeholder="请选择年份" @change="changeHandle">
        <el-option
          v-for="item in options"
          :key="item"
          :label="item"
          :value="item"
        />
      </el-select>
      <el-select v-model="month" placeholder="请选择月" @change="changeHandle">
        <el-option v-for="item in 12" :key="item" :label="item" :value="item" />
      </el-select>
    </div>
    <el-calendar v-model="value">
      <template
        slot="dateCell"
        slot-scope="{ date }"
      >
        {{ new Date(date).getDate() }}
        <!-- 这里加载出的每个日期最外层是一个盒子  这里设置的什么标签  盒子里面就是什么标签 -->
        <span v-if="getDay(date)" style="background: red; color: #fff"></span>
        <p v-if="checkDay(date)" style="color: skyblue">清明</p>
      </template>
    </el-calendar>
  </div>
</template>
<script>
export default {
  name: 'Calendar',
  data() {
    return {
      value: new Date(),
      options: [2021, 2022, 2023],
      year: new Date().getFullYear(),
      month: new Date().getMonth() + 1
    }
  },
  computed: {},
  created() {
    /* 如何将伪数组转换成真数组  */
    // console.log([...Array(11)]);
    // console.log(Array.from(Array(11)));
    var arr = Array.from(Array(11))
    arr.forEach((item, index) => {
      // console.log(item + index, 99);
      // console.log(index - 5 + 2022, 99);
      // item = index - 5 + 2022;
      arr[index] = index - 5 + this.year
    })
    this.options = arr
  },
  updated() {
    // 这里获取了更新后的新日期
    // console.log(this.value, 777777777777777)
    // console.log(new Date(this.value), 666666666)
    // console.log(new Date(this.value).getFullYear(), 77777777)
    // console.log(new Date(this.value).getMonth() + 1, 88888888)
    // 上下时间绑定
    // 调用 getFullYear方法 需要前面的时间的格式符合标准
    this.year = new Date(this.value).getFullYear()
    this.month = new Date(this.value).getMonth() + 1
  },
  methods: {
    changeHandle() {
      // 这里实现了下拉框 控制 日历内容功能
      this.value = `${this.year}-${this.month}`
      console.log(this.value, 999)
    },
    getDay(t) {
      //  在 scoped-slot 可以获取到 date(当前单元格的日期)
      // console.log(t, 888888)
      const day = t.getDay()
      if (day === 6 || day === 0) {
        return true
      } else {
        return false
      }
      // console.log(day, 7777777)
    },
    checkDay(t) {
      const y = t.getFullYear()
      const m = t.getMonth() + 1
      const d = t.getDate()
      console.log(y, m, d, 666666)
      if (y === 2022 && m === 4 && d === 5) {
        return true
      }
      return false
    }
  }
}
</script>
<style lang="scss" scoped>
/* 穿透
scss  ::v-deep
less  /deep/

*/
.el-calendar {
  ::v-deep .el-calendar__header {
    display: none;
  }
}
</style>