【无标题】基于element ui封装只有月和日的日期选择器

封装月、日日期组件

效果如图:
【无标题】基于element ui封装只有月和日的日期选择器_第1张图片
封装的显示展示日期格式为X月X日,转载的原作者封装的是格式是X-X,可以参考一下,修改成自己需要的格式.

  1. 首先封装一个月日组件,新建文件DateMonthDay.vue
<template>
  <div>
    <el-popover
      placement="bottom"
      width="280"
      v-model="visible">
      <div class="date-month-day">
        <div class="header">
          <div class="left-arrow" @click="dirClick('left')"><i class="el-icon-arrow-left" />div>
          <div v-text="getMonthFormat" @click="monthTile" style="cursor: pointer">div>
          <div class="right-arrow" @click="dirClick('right')">
            <i class="el-icon-arrow-right" />
          div>
        div>
        <div class="content" v-if="monthShow">
          <div class="month" v-for="(item) in getMonths" :key="item.key" @click="monthClick(item)">
            <span :class="activeMonth(item.key)">{{item.value}}span>div>
        div>
        <div class="content" v-else>
          <div class="day" v-for="(item) in getDays" :key="item" @click="dayClick(item)">
            <span :class="activeDay(item)">{{item}}span>div>
        div>
      div>
      <el-input
        slot="reference"
        :placeholder="placeholder"
        prefix-icon=""
        :style="`cursor: pointer;width: ${width} !important;`"
        :clearable="true"
        :readonly="true"
        v-model="dateVal">
      el-input>
    el-popover>
  div>

template>

<script>
import moment from 'moment'; // 导入日期插件

export default {
  props: {
    // 默认值
    dateDefault: {
      type: String,
    },
    // 居中排列
    placeholder: {
      type: String,
      default: '选择日期',
    },
    // 默认年份,闰年
    year: {
      type: String,
      default: '2020',
    },
    // 宽度
    width: {
      type: String,
      default: '130px',
    },
  },
  data() {
    return {
      visible: false,
      monthShow: false,
      monthFormat: {
        1: '一月',
        2: '二月',
        3: '三月',
        4: '四月',
        5: '五月',
        6: '六月',
        7: '七月',
        8: '八月',
        9: '九月',
        10: '十月',
        11: '十一月',
        12: '十二月',
      },
      dateVal: '',
      monthVal: '',
      dayVal: '',
    };
  },
  computed: {
    getMonthFormat() {
      return this.monthVal ? this.monthFormat[Number(this.monthVal)] : '';
    },
    // 默认选中天
    activeDay() {
      // eslint-disable-next-line func-names
      return function (item) {
        return Number(this.dayVal) === item ? 'active' : '';
      };
    },
    // 默认选中月
    activeMonth() {
      // eslint-disable-next-line func-names
      return function (item) {
        return this.monthVal === item ? 'active' : '';
      };
    },
    // 获取当前月的天数
    getDays() {
      let days = 30;
      const bigMonth = [1, 3, 5, 7, 8, 10, 12];
      if (this.monthVal && bigMonth.includes(Number(this.monthVal))) {
        days = 31;
      } else if (this.monthVal && Number(this.monthVal) === 2) {
        days = 28;
        if (Number(this.year) % 4 === 0) {
          days = 29;
        }
      }
      return days;
    },
    // 获取月份
    getMonths() {
      const mon = [];
      // 注意
      Object.keys(this.monthFormat).forEach(m => {
        mon.push({
          key: `${m}`,
          value: this.monthFormat[m],
        });
      });
      // for (let m in this.monthFormat) {
      //   mon.push({
      //     key: `${m}`,
      //     value: this.monthFormat[m],
      //   });
      // }
      return mon;
    },
  },
  watch: {
    dateDefault: {
      handler(newVal) {
        if (newVal) {
          const defaultDate = `${this.year}-${this.dateDefault}`;
          this.dateVal = moment(defaultDate).format('M月D日');
          this.monthVal = moment(defaultDate).format('M');
          this.dayVal = moment(defaultDate).format('D');
        } else {
          this.dateVal = moment().format('M月D日');
          this.monthVal = moment().format('M');
          this.dayVal = moment().format('D');
          this.$emit('update:date', this.dateVal);
        }
      },
      immediate: true, // immediate选项可以开启首次赋值监听
    },
    visible: {
      handler(newVal) {
        if (newVal) {
          if (this.dateDefault) {
            // 按照闰年来算,防止出现29号,算到1号
            const defaultDate = `${this.year}-${this.dateDefault}`;
            this.dateVal = moment(defaultDate).format('M月D日');
            this.monthVal = moment(defaultDate).format('M');
            this.dayVal = moment(defaultDate).format('D');
          } else {
            this.dateVal = moment().format('M月D日');
            this.monthVal = moment().format('M');
            this.dayVal = moment().format('D');
            this.$emit('update:date', this.dateVal);
          }
        } else {
          this.monthShow = false;
          this.$emit('sureValid');
        }
      },
      immediate: true, // immediate选项可以开启首次赋值监听
    },
  },
  methods: {
    dirClick(type) {
      if (type === 'left') {
        if (Number(this.monthVal) === 1) {
          this.monthVal = '12';
        } else {
          this.monthVal = moment(this.monthVal).subtract(1, 'M').format('M');
        }
      }
      if (type === 'right') {
        if (Number(this.monthVal) === 12) {
          this.monthVal = '1';
        } else {
          this.monthVal = moment(this.monthVal).add(1, 'M').format('M');
        }
      }

      // 默认选中
      let month = moment().format('M');
      let day = moment().format('D');
      if (this.dateDefault) {
        month = moment(this.dateDefault).format('M');
        day = moment(this.dateDefault).format('D');
      }
      if (month === this.monthVal) {
        this.dayVal = Number(day);
      } else {
        this.dayVal = '';
      }
    },
    monthTile() {
      this.monthShow = true;
    },
    monthClick(month) {
      this.monthVal = month.key;
      this.dirClick();
      this.monthShow = false;
    },
    dayClick(item) {
      this.dayVal = item;
      const day = `${this.dayVal}`;
      const val = {
        day,
        month: this.monthVal,
        date: `${this.monthVal}-${day}`,
      };
      this.$emit('update:date', val.date);
      this.$emit('changeDay', val);
      this.visible = false;
      this.$emit('sureValid');
    },
    focus() {
      this.$emit('sureValid');
    },
  },
};
script>

<style lang="less" scoped>
  .date-month-day{

    .header{
      display: -webkit-flex; /* Safari */
      display: flex;
      text-align: center;
      flex-direction: row;
      align-items: center;
      justify-content: space-between;
      border-bottom: 1px solid #ebeef5;
      .left-arrow,.right-arrow{
        cursor: pointer;
        width: 30px;
        height: 36px;
        line-height: 36px;
        font-size: 14px;
        color: #42424D;
        z-index: 9;
        background: #fff;
      }
    }
    .content{
      display: -webkit-flex; /* Safari */
      display: flex;
      text-align: center;
      flex-direction: row;
      align-items: center;
      flex-wrap: wrap;
      margin-top: 10px;
      .day{
        width: calc(100% / 7);
        height: 36px;
        padding: 4px 0;
        box-sizing: border-box;
        text-align: center;
        cursor: pointer;
        position: relative;
        span{
          width: 24px;
          height: 24px;
          display: block;
          margin: 0 auto;
          line-height: 24px;
          position: absolute;
          left: 50%;
          transform: translateX(-50%);
          border-radius: 50%;
        }
        .active{
          color: #fff;
          background-color: #409eff;
        }
      }
      .month{
        width: calc(100% / 4);
        height: 48px;
        padding: 6px 0;
        box-sizing: border-box;
        cursor: pointer;
        span{
          width: 60px;
          height: 36px;
          display: block;
          line-height: 36px;
          color: #606266;
          margin: 0 auto;
          border-radius: 18px;
        }
        .active{
          color: #fff;
          background-color: #409eff;
        }
      }
    }
    ::v-deep{
      .el-input{
        width: 120px;
        z-index: 9;
      }
      .el-input__inner{
        cursor: pointer;
        border: none;
        text-align: center;
        padding: 0px;
        color: #42424D;
      }
    }
  }
style>


  1. 使用dateMonthDay.vue组件
 <DateMonthDay @sureValid="endSure(index)"
   :year="String(year+item.end.year)"
   class="date-select" :date.sync="date"
   :dateDefault="item.end.date">
DateMonthDay>

传给子组件参数说明:

  • year
    传递的年,根据传入的年获取月展示的天数,不同年天数可能不一样,比如闰年2月和平年2月
  • date和dateDefault
    有点忘了,设置成一样的就行,反正是传入的日期,传入的格式为X-x,比如1-1,3-19,获取到的日期格式也是X-x
  • sureValid事件,endSure方法,可以写自己的对日期的校验方法,比如我的校验方法,要求结束时间必须在开始时间之后
endSure(index) {
      const item = this.sessionList[index];
      if (new Date(item.end.date) <= new Date(item.start.date)) {
        this.$message({
          message: '结束时间必须在开始时间之后',
          type: 'error',
          customClass: 'message-info',
        });
      }
    },
  • placeholder
    没给默认值时候的占字符

转载自https://blog.csdn.net/zsl471260400/article/details/116654979

你可能感兴趣的:(vue组件,前端,vue.js,elementui)