antd封装年份组件,不允许选择未来的年份mode=‘year‘

1、DatePicker组件在设置mode=‘year’ disabledDate不生效,不能禁止年单位的选择(新版本才可以!)

github地址

2、自己封装了一个,效果(今年为2021年):

在这里插入图片描述

3、组件html
<template>
  <!-- 年份组件 -->
  <div class="yearDate">
    <div class="inputBox">
      <a-input
        v-model="year"
        class="yearInput"
        @click="showDate"
      />
      <a-icon type="calendar" />
    </div>
    <div class="content">
      <div class="chooseBox" ref="listHeight" style="box-shadow: 0 2px 8px rgb(0 0 0 / 15%);" v-show="showList" @mouseleave="handleLeave">
        <a-input
          ref="modFocus"
          v-model="newYear"
          class="modInput"
          @blur="handleBlur"
        />
        <div class="footer">
          <div class="btnBox">
            <span class="left" @click="handleOld" v-show="isMoreOld">
              <a-icon type="double-left" />
            </span>
            <span class="mid">{{dateSlot}}</span>
            <span class="right" @click="handleNow" v-show="isMoreNow">
              <a-icon type="double-right" />
            </span>
          </div>
          <div class="listBox">
            <ul>
              <li v-for="(item, index) in dateShowList" :key="index" @click="edit(item)">
                <span :class="{'active': active == index}">{{item.name}}</span>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'yearDate',
  props: ['year'],
  data() {
    return {
      active: 0, // 选中
      dateSlot: '', // 显示的年份区间
      dateList: { // 所有年份(暂时只做三个区间)
        now: [],
        old: [],
        moreOld: []
      },
      isMoreOld: true, // 左右箭头显隐
      isMoreNow: true,
      dateShowList: [], // 展示的年份
      showList: false, // 展示年份面板的显隐
      newYear: '', // 新的输入框
      isSel: false, // 点击选中的
      isLeave: false, // 面板鼠标移出
      minRange: '', // 中间的年份区间
      isBlur: false // 输入框失去焦点
    }
  },
  mounted() {
  },
  methods: {
 	// 获取输入的值,用于判断不能超过今年年度
    getInputYear(e) {
      if(Number(e.target.value) > Number(new Date().getFullYear())) {
        // this.newYear = new Date().getFullYear();
        this.newYear = this.year;
      }
    },
    // 获取展示的数据
    getList() {
      // 每次都置空
      this.dateList.now = []
      this.dateList.old = []
      this.dateList.moreOld = []
      // 给总年份数据赋值(根据今年的年份往以前的算)
      let newYear = new Date().getFullYear()
      for(let i = 0; i < 12; i++) {
        this.dateList.now.push({
          id: i,
          name: newYear - (11 - i)
        })
        this.dateList.old.push({
          id: i,
          name: newYear - (11*2 + 1 - i)
        })
        this.dateList.moreOld.push({
          id: i,
          name: newYear - (11*3 + 2 - i)
        })
      }
      // 因为数据只有三页,所以取中间的年份区间就够了,用于左右箭头的判断
      this.minRange = String(this.dateList.old[0].name) + '-' +  String(this.dateList.old[11].name)
      // 判断处在哪个年份区间
      if(newYear >= Number(this.year) && Number(this.year) >= (newYear - 11)) {
        this.dateShowList = this.dateList.now
        // 左右箭头显隐
        this.isMoreNow = false
        this.isMoreOld = true
        // 过滤,对应的年份样式赋值
        this.dateList.now.filter( val => {
          if(val.name == Number(this.year)) {
            this.active = val.id
          }
        })
      } else if (newYear - 12 >= Number(this.year) && Number(this.year) >= (newYear - 22)) {
        this.dateShowList = this.dateList.old
        this.isMoreNow = true
        this.isMoreOld = true
        this.dateList.old.filter( val => {
          if(val.name == Number(this.year)) {
            this.active = val.id
          }
        })
      } else {
        this.dateShowList = this.dateList.moreOld
        this.isMoreNow = true
        this.isMoreOld = false
        this.dateList.moreOld.filter( val => {
          if(val.name == Number(this.year)) {
            this.active = val.id
          }
        })
      }
      // 获取年份区间
      this.dateSlot = String(this.dateShowList[0].name) + '-' +  String(this.dateShowList[11].name)
    },
    // 点击右箭头
    handleNow() {
      // 最新年份没有右箭头,无需判断
      if(this.dateSlot == this.minRange) {
        // 在中,右往最新
        this.dateShowList = this.dateList.now
        this.isMoreNow = false
        this.isMoreOld = true
      } else {
        // 不为中,则低,右往中间
        this.dateShowList = this.dateList.old
        this.isMoreNow = true
        this.isMoreOld = true
      }
      // 年份区间展示
      this.dateSlot = String(this.dateShowList[0].name) + '-' +  String(this.dateShowList[11].name)
    },
    // 点击左箭头
    handleOld() {
      // 最老年份没有左箭头,无需判断
      if(this.dateSlot == this.minRange) {
        // 在中,左往最老
        this.dateShowList = this.dateList.moreOld
        this.isMoreNow = true
        this.isMoreOld = false
      } else {
        this.dateShowList = this.dateList.old
        this.isMoreNow = true
        this.isMoreOld = true
      }
      // 年份区间展示
      this.dateSlot = String(this.dateShowList[0].name) + '-' +  String(this.dateShowList[11].name)
    },
    // 点击旧输入框
    showDate() {
      this.getList()
      this.showList = true
      this.newYear = this.year
      this.$nextTick(() => {
        // 自动获取焦点
        this.$refs.modFocus.focus()
        // 旧输入框图标隐藏
        document.querySelector(".anticon-calendar svg").style.display = 'none'
      })
    },
    // 点击年份
    edit(item) {
      this.isSel = true
      // 输入框失去焦点并且点击了某个年份
      if(this.isSel) {
        this.active = item.id
        this.showList = false
        this.$nextTick(() => {
          // 传值给父组件
          this.$emit('getYear', item.name)
          // 旧输入框图标显示
          document.querySelector(".anticon-calendar svg").style.display = 'inline-block'
        })
      }
      this.isLeave = false
      this.isBlur = false
      this.isSel = false
    },
    // 失去焦点
    handleBlur() {
      this.isBlur = true
    },
    // 鼠标移出弹窗
    handleLeave() {
      this.isLeave = true
      // 必须要延迟触发,不然失去焦点没触发到就直接执行了
      clearTimeout(timer)
      var timer = setTimeout(() => {
        if(this.isLeave && this.isBlur) {
          // 判断输入框的值
          if(this.newYear.length == 4 && Number(this.newYear) < Number(this.year + 1)) {
            this.$emit('getYear', this.newYear)
          } else {
            // 用回默认值
            this.$emit('getYear', this.year)
          }
          // 显示旧输入框
          document.querySelector(".anticon-calendar svg").style.display = 'inline-block'
          this.showList = false
        }
        this.isBlur = false
        this.isLeave = false
        this.isSel = false
      }, 500);
    },
  }
}
</script>
<style lang="less" scoped>
@import "index";
</style>
<style lang="less">
// 年份组件公共样式
.yearDateCommon { // 父组件必须加的类名(防止数据太少,页面高度小于年份组件要展示的高度)
  min-height: 64vh;
}
</style>

4、组件样式less
.yearDate {
  position: relative;

  .inputBox {
    position: relative;

    /deep/ .anticon-calendar {
      position: absolute;
      right: 10px;
      line-height: 32px;
    }
  }

  .content {
    // height: 44px;
    .chooseBox {
      position: absolute;
      top: 0px;
      left: 0px;
      width: 280px;
      font-size: 14px;
      line-height: 1.5;
      text-align: left;
      list-style: none;
      background-color: #fff;
      background-clip: padding-box;
      border: 1px solid #fff;
      border-radius: 4px;
      outline: none;
      -webkit-box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
      box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
      z-index: 2021;
      .modInput {
        border: none;
        outline: none;
        box-shadow: none;
      }

      .btnBox {
        display: flex;
        height: 40px;
        line-height: 40px;
        padding: 0px 10px;
        border-top: 1px solid #f0f0f0;
        border-bottom: 1px solid #f0f0f0;

        .left {
          width: 20px;
          color: rgba(0, 0, 0, 0.45);
          cursor: pointer;
        }

        .mid {
          flex: 1;
          color: rgba(0, 0, 0, 0.85);
          font-weight: 500;
          text-align: center;
        }

        .right {
          width: 20px;
          color: rgba(0, 0, 0, 0.45);
          text-align: right;
          cursor: pointer;
        }
      }

      .listBox {
        ul {
          display: flex;
          flex-wrap: wrap;

          li {
            width: 33.3%;
            line-height: 54px;
            text-align: center;

            span {
              display: inline-block;
              height: 24px;
              margin: 0 auto;
              padding: 0 8px;
              color: rgba(0, 0, 0, 0.65);
              line-height: 24px;
              text-align: center;
              background: transparent;
              border-radius: 2px;
              cursor: pointer;
              &:hover {
                color: #3d9eff;
                background: #e6f6ff;
              }
            }

            .active {
              color: #fff;
              background: #1385ff;
            }
          }
        }
      }
    }
  }

}

/deep/ .anticon-calendar {
  color: rgba(0, 0, 0, 0.25);
  ;
}
5、页面中使用
<template>
  <div class="monthCheck yearDateCommon">
    <div class="searchBox">
      <a-form layout="horizontal" class="searchForm" :form="searchForm">
        <div class="inputBox">
          <a-form-item label="年度:" class="yearSearch">
            <year-date @getYear="getYear" :year="year" />
          </a-form-item>
        </div>
        <div class="btnBox">
          <a-button
            type="primary"
            icon="search"
            class="item-btn"
            style="background: #108ee9"
            @click="handleSearch"
            >搜索</a-button
          >
          <a-button icon="sync" @click="reset"> 重置 </a-button>
        </div>
      </a-form>
    </div>
   </div>
 </template>
 <script>
import yearDate from "@/components/yearDate/index";
export default {
	components: {
	    yearDate
	},
	data() {
    return {
      year: new Date().getFullYear(), // 默认当前的年份
    };
  },
  created() {
    this.$nextTick(() => {
      this.getData();
    });
  },
  methods: {
	// 请求表格数据
    async getData() {
      let year = String(this.year);
      this.dataLoad = true;
      let res = await this.$http(
        this.$url.FAULT_RESPONSE_MONTH_LIST + year,
        "get"
      );
      this.dataLoad = false;
      if (res.data.code === 0) {
        this.dataSource = res.data.data;
      } else {
        this.dataSource = [];
      }
    },
    // 获取年份子组件的数据
    getYear(data) {
      this.year = String(data);
    },
  }
}
</script>
6、注意两个细节:1是箭头判断和年份区间展示;2是组件展示在父组件中的高度样式(公用类名:yearDateCommon )

广州加油,广东加油,中国加油!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值