vue+element自定义日历公共组件

 需求页面样式如下

 

 代码可直接复制使用

<template>
  <div>
    <div class="calendar">
      <div class="calendarHeader">
        <div style="float: left" class="cursor" @click="goPreviousYear()">
          <!-- <div class="lineleft"></div>
          <div class="lineleft"></div> -->
          <i class="el-icon-d-arrow-left"></i>
        </div>
        <i class="el-icon-arrow-left cursor" @click="goPreviousMonth()"></i>
        <b style="margin: 0px 15px; display: inline-block; color: #333">
          {{ currentMonth }}
        </b>
        <i class="el-icon-arrow-right cursor" @click="goNextMonth()"></i>
        <div style="float: right" class="cursor" @click="goNextYear()">
          <!-- <div class="lineright"></div>
          <div class="lineright"></div> -->
          <i class="el-icon-d-arrow-right"></i>
        </div>
      </div>
      <div class="calendarMain">
        <div class="calendarMainHeader">
          <span v-for="(item, index) in weekDay" :key="index" class="weekItem">
            {{ item.name }}
          </span>
        </div>
        <div class="calendarMainBody">
          <span
            v-for="(item, index) in dateList"
            :key="index"
            class="dataItem cursor"
            @click="handleClick(item, $event)"
          >
            <span
              class="hoverStyle"
              :class="[
                { color666: item.type !== 'current' },
                {
                  checkStyle:
                    selectTime === `${item.year}-${item.month}-${item.day}`,
                },
                { color666: disable },
                { color666: ableClick(item) },
              ]"
              >{{ item.value }}</span
            >
          </span>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    time: {}, //(yyyy-mm) 当前显示月份(初始化一次 不做后期同步)
    selectTime: {}, // (yyyy-mm-dd) 当前选中的日期(单向数据流)
    disable: {
      //是否禁止选择日期 (用于起始 结束日期的禁止联动)
      type: Boolean,
      default: false,
    },
    isdataCheck: {
      //是否禁止某个日期以前的时间不可选(与CheckData参数搭配使用)
      type: Boolean,
      default: false,
    },
    CheckData: {
      //yyyy-mm-dd)禁止某个日期以前的时间不可选的日期 (isdataCheck为true时生效)
      type: String,
      default: "",
    },
  },
  data() {
    return {
      newTime: this.time,
      selectValue: this.selectTime,
      weekDay: [
        {
          name: "一",
          code: "Monday",
        },
        {
          name: "二",
          code: "Tuesday",
        },
        {
          name: "三",
          code: "Wednesday",
        },
        {
          name: "四",
          code: "Thursday",
        },
        {
          name: "五",
          code: "Friday",
        },
        {
          name: "六",
          code: "Saturday",
        },
        {
          name: "日",
          code: "Sunday",
        },
      ],
      dateList: [],
    };
  },
  computed: {
    currentMonth() {
      return `${this.newTime.split("-")[0]}年${this.newTime.split("-")[1]}月`;
    },
  },
  methods: {
    goPreviousYear() {
      let a = this.newTime.split("-");
      a[0] = a[0] - 1;
      this.newTime = a.join("-");
      this.dataListNew(this.newTime, this.newTime);
      this.$emit("changeTime", this.newTime);
    },
    goNextYear() {
      let a = this.newTime.split("-");
      a[0] = a[0] * 1 + 1;
      this.newTime = a.join("-");
      this.dataListNew(this.newTime, this.newTime);
      this.$emit("changeTime", this.newTime);
    },
    goPreviousMonth() {
      this.newTime = this.previousMonth(this.newTime);
      this.dataListNew(this.newTime, this.newTime);
      this.$emit("changeTime", this.newTime);
    },
    goNextMonth() {
      this.newTime = this.nextMonth(this.newTime);
      this.dataListNew(this.newTime, this.newTime);
      this.$emit("changeTime", this.newTime);
    },
    goNowTime() {
      this.newTime = this.getTime();
      this.dataListNew(this.newTime, this.newTime);
      this.$emit("changeTime", this.newTime, "nowTime");
    },
    getTime() {
      let today = new Date();
      let year = today.getFullYear();
      let month = today.getMonth() + 1;
      let days = today.getDate();
      let newTime = `${year}-${this.formateDate(month)}-${this.formateDate(
        days
      )}`;
      return newTime;
    },
    formateDate(str) {
      return str < 10 ? "0" + str : str;
    },
    // 生成当月长度数组
    listNew(time, type) {
      let x = time.split("-");
      let a = new Date(x[0], x[1], 0).getDate();
      let b = Array.from(new Array(a).keys());
      let c = [];
      b.forEach((item) => {
        c.push({
          value: item + 1,
          type: type,
          year: x[0],
          month: x[1],
          day: (item + 1 + "").padStart(2, "0"),
          select: false,
        });
      });
      return c;
    },
    // 计算上个月日期
    previousMonth(time) {
      let a = time.split("-");
      if (a[1] == "01") {
        a[0] = a[0] - 1;
        a[1] = "12";
      } else {
        a[1] = (a[1] - 1 + "").padStart(2, "0");
      }
      return a.join("-");
    },
    // 计算下个月日期
    nextMonth(time) {
      let a = time.split("-");
      if (a[1] == "12") {
        a[0] = a[0] * 1 + 1;
        a[1] = "01";
      } else {
        a[1] = (a[1] * 1 + 1 + "").padStart(2, "0");
      }
      return a.join("-");
    },
    // 汇总数据 生成日期数组
    dataListNew(startTime, endTime) {
      this.dateList = [];
      // 开始时间
      let a = startTime.split("-");
      // 结束时间
      let b = endTime.split("-");
      // 上个月的日期
      let c = this.previousMonth(startTime).split("-");
      let d = this.listNew(this.previousMonth(startTime), "previous");
      c[2] = d[d.length - 1].value;
      let J = new Date(c.join("-")).getDay();
      let k = [];
      if (J !== 0) {
        k = d.splice(J * -1);
      }
      // 下个月的日期
      let e = this.nextMonth(endTime).split("-");
      let f = this.listNew(this.nextMonth(endTime), "next");
      e[2] = f[0].value;
      let L = new Date(e.join("-")).getDay();
      let G = [];
      G = f.splice(0, 8 - L);
      // 拼接上个月的数据
      this.dateList = this.dateList.concat(k);
      // 拼接当前月的数据
      this.dateList = this.dateList.concat(
        this.listNew(a.join("-"), "current")
      );
      // 拼接间隔月的数据
      while (a.join("-") !== b.join("-")) {
        if (a[1] == "12") {
          a[0] = a[0] * 1 + 1;
          a[1] = "01";
        } else {
          a[1] = (a[1] * 1 + 1 + "").padStart(2, "0");
        }
        // 拼接下个月的数据
        this.dateList = this.dateList.concat(this.listNew(a.join("-")));
      }
      this.dateList = this.dateList.concat(G);
    },
    handleClick(item, e) {
      if (e.target.className.indexOf("color666") > 0) {
        return;
      }
      this.$emit("startDataHandle", `${item.year}-${item.month}-${item.day}`);
    },
    ableClick(item) {
      if (this.isdataCheck) {
        return (
          Date.parse(new Date(`${item.year}-${item.month}-${item.day}`)) <
          Date.parse(new Date(this.CheckData))
        );
      } else {
        return false;
      }
    },
  },
  created() {
    this.dataListNew(this.newTime, this.newTime);
  },
  watch: {
    time: function (newValue) {
      this.selectValue = newValue;
    },
    disable: function (newValue) {
      //console.log(newValue);
    },
  },
};
</script>

<style scoped="scoped">
.calendar {
  width: 285px;
  height: 318px;
}
.calendarHeader {
  width: 280px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  padding: 0px 5px;
  box-sizing: border-box;
}

.calendarMain {
  width: 285px;
  height: 268px;
  box-sizing: border-box;
  font-size: 14px;
}

.lineright {
  width: 5px;
  height: 5px;
  transform: rotate(45deg);
  display: inline-block;
  border-top: 1px solid #000;
  border-right: 1px solid #000;
}

.lineleft {
  width: 5px;
  height: 5px;
  transform: rotate(-135deg);
  display: inline-block;
  border-top: 1px solid #000;
  border-right: 1px solid #000;
}

.calendarMainHeader {
  /* display: flex; */
  background: #f0f8ff;
  color: #1e9bff;
}

.weekItem {
  display: inline-block;
  width: calc(100% / 7 - 6px);
  height: 34.85px;
  line-height: 34.85px;
  margin: 0px 3px;
  text-align: center;
}

.calendarMainBody {
  /* display: flex;
		flex-wrap: wrap; */
}

.dataItem {
  display: inline-block;
  width: calc(100% / 7 - 6px);
  height: 34.85px;
  line-height: 34.85px;
  margin: 0px 3px;
  text-align: center;
}

.color666 {
  color: #ccc;
  cursor: not-allowed !important;
}

.cursor {
  cursor: pointer;
}

.checkStyle {
  border-radius: 50%;
  background-color: #1e9bff;
  color: white;
  display: inline-block;
  height: 25px;
  width: 25px;
  line-height: 25px;
}

.hoverStyle:hover {
  border-radius: 50%;
  background-color: #1e9bff;
  color: white;
  display: inline-block;
  height: 25px;
  width: 25px;
  line-height: 25px;
}
</style>

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值