0


vue element-ui年份范围选择器,年日期插件,可选日期区间等

可以禁止选择未来日期,以及可选的日期范围控制,代码在最下面。

直接上代码:
先来一个不禁止选择的示例

<template><el-popover
    ref="popover"placement="bottom"
    v-model="showPanel"
    popper-class="custom_year_range"trigger="manual"
    v-clickoutside="() => { showPanel = false }"><div class="_inner floatPanel"><div class="_inner leftPanel"><div class="_inner panelHead"><i
            class="_inner el-icon-d-arrow-left"
            @click="onClickLeft"></i><span>{{ leftYearList[0] + '年 ' + '- ' + leftYearList[9] + '年'}}</span></div><div class="_inner panelContent"><div
            :class="{
              oneSelected: item === startYear && oneSelected,
              startSelected: item === startYear,
              endSelected: item === endYear,
              betweenSelected: item > startYear && item < endYear,
            }"
            v-for="item in leftYearList"
            :key="item"><a
              :class="{
                cell: true,
                _inner: true,
                selected: item === startYear || item === endYear,
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div><div class="_inner rightPanel"><div class="_inner panelHead"><i
            class="_inner el-icon-d-arrow-right"
            @click="onClickRight"></i><span>{{ rightYearList[0] + '年 ' + '- ' + rightYearList[9] + '年'}}</span></div><div class="_inner panelContent"><div
            :class="{
              startSelected: item === startYear,
              endSelected: item === endYear,
              betweenSelected: item > startYear && item < endYear,
            }"
            v-for="item in rightYearList"
            :key="item"><a
              :class="{
                cell: true,
                _inner: true,
                selected: item === endYear || item === startYear,
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div></div><div slot="reference"><div
        ref="yearPicker"style="width: 100%"class="el-date-editor el-range-editor el-input__inner el-date-editor--daterange el-range-editor--small"><i class="el-input__icon el-range__icon el-icon-date"></i><input
          class="_inner range_input"ref="inputLeft"type="text"name="yearInput"placeholder="选择开始年份"
          v-model="startShowYear"
          @focus="onFocus"
          @keyup="handleInput('start')"
        /><span class="el-range-separator">{{ sp }}</span><input
          class="_inner range_input"ref="inputRight"type="text"name="yearInput"placeholder="选择结束年份"
          v-model="endShowYear"
          @focus="onFocus"
          @keyup="handleInput('end')"
        /></div></div></el-popover></template><script>import moment from 'moment'import{ clickoutside, SELECT_STATE } from './yearDate.js'export default {
  name: 'yearPicker',
  directives: { clickoutside },
  computed: {oneSelected(){return this.curState === SELECT_STATE.selecting &&(this.startYear === this.endYear || this.endYear == null)},
    leftYearList(){return this.yearList.slice(0, 10)},
    rightYearList(){return this.yearList.slice(10, 20)}},
  props: {
    sp: {
      default: '至'},
    value: {
      default: null
    }},
  data(){return{
      itemBg: {},
      startShowYear: null,
      endShowYear: null,
      yearList: [],
      showPanel: false,
      startYear: null,
      endYear: null,
      curYear: 0,
      curSelectedYear: 0,
      curState: SELECT_STATE.unselect
    }},
  methods: {
    handleInput(type){
      switch (type){case'start':if(isNaN(this.startShowYear)){
            this.startShowYear = this.startYear
            return}
          this.startYear = this.startShowYear * 1breakcase'end':if(isNaN(this.endShowYear)){
            this.endShowYear = this.endYear
            return}
          this.endYear = this.endShowYear * 1break}[this.startYear, this.endYear]=[this.endYear, this.startYear]
      this.startShowYear = this.startYear
      this.endShowYear = this.endYear
    },

    onHoverItem(iYear){if(this.curState === SELECT_STATE.selecting){
        const tmpStart = this.curSelectedYear
        this.endYear = Math.max(tmpStart, iYear)
        this.startYear = Math.min(tmpStart, iYear)}},

    async onClickItem(selectYear){if(
        this.curState === SELECT_STATE.unselect ||
        this.curState === SELECT_STATE.selected
      ){
        this.startYear = selectYear
        this.curSelectedYear = selectYear
        this.endYear = null
        this.curState = SELECT_STATE.selecting
      }elseif(this.curState === SELECT_STATE.selecting){
        this.endShowYear = this.endYear || this.startYear
        this.startShowYear = this.startYear
        this.curState = SELECT_STATE.selected
        await this.$nextTick()
        this.showPanel =false
        this.$parent?.$parent?.$parent?.$parent?.$parent.clearValidate?.()}},

    async onFocus(){
      await this.$nextTick()
      this.showPanel =true},

    updateYearList(){
      const startYear = ~~(this.curYear / 10) * 10
      console.log(startYear, this.curYear, 'this.curYearthis.curYearthis.curYear')
      this.yearList =[]for(let index =0; index <20; index++){
        this.yearList.push(startYear + index)}},

    onClickLeft(){
      this.curYear = this.curYear * 1 - 10
      this.updateYearList()},

    onClickRight(){
      this.curYear = this.curYear * 1 + 10
      this.updateYearList()}},
  watch: {
    value: {
      handler(val){if(val?.length ===0)return
        const [first, end]= val ||[]
        this.startShowYear = first
        this.endShowYear = end
      },
      immediate: true,
      deep: true},

    startShowYear: {
      handler(val){
        this.$emit('input', [val, this.endShowYear ||''])},
      immediate: true,
      deep: true},

    endShowYear: {
      handler(val){
        this.$emit('input', [this.startShowYear ||'', val])},
      immediate: true,
      deep: true}},
  created(){
    const [startYear, endYear]= this.value ||[]if(startYear){
      this.startYear = Number(startYear)
      this.endYear = Number(endYear)
      this.curState = SELECT_STATE.selected
      this.curYear = startYear
    }else{
      this.curYear = moment().format('yyyy')}
    this.updateYearList()},

  mounted(){
    window.Vue = this
  }}</script><style lang="scss">
.custom_year_range {
  .floatPanel {> div {
      width: 50%;}
    padding: 0 16px;
    // position: absolute;
    display: flex;
    background-color: #fff;
    z-index: 2000;
    border-radius: 4px;
    width: 650px;
    height: 250px;
    top: 40px;
    left: -50px;
    .panelContent {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
      height: calc(100% - 70px);
      .oneSelected {
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;}
      .startSelected {
        background-color: #f2f6fc;
        border-top-left-radius: 24px;
        border-bottom-left-radius: 24px;}
      .endSelected {
        background-color: #f2f6fc;
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;}
      .betweenSelected {
        background-color: #f2f6fc;}> div {
        width: 75px;
        height: 48px;
        line-height: 48px;
        margin: 3px 0;
        // border-radius: 24px;
        text-align: center;
        a {
          display: inline-block;
          width: 60px;
          height: 36px;
          cursor: pointer;
          line-height: 36px;
          border-radius: 18px;&:hover {
            color: #409eff;}}
        .selected {
          background-color: #409eff;
          color: #fff;&:hover {
            color: #fff !important;}}}}
    .panelHead {
      position: relative;
      height: 46px;
      line-height: 46px;
      text-align: center;
      display: flex;
      align-items: center;
      justify-content: center;
      span {
        font-size: 16px;
        font-weight: 500;
        padding: 0 5px;
        line-height: 22px;
        text-align: center;
        cursor: pointer;
        color: #606266;&:hover {
          color: #409eff;}}
      i {
        position: absolute;
        cursor: pointer;&:hover {
          color: #3e77fc;}}}
    .rightPanel {
      padding-left: 8px;}
    .leftPanel .panelHead i {
      left: 20px;}
    .rightPanel .panelHead i {
      right: 20px;}}
  .floatPanel::before {
    content: "";
    height: 100%;
    top: 0;
    position: absolute;
    left: 50%;
    width: 1px;
    border-left: 1px solid #e4e4e4;}}</style><style lang="scss" scoped>
.range_input {
  appearance: none;
  border: none;
  outline: 0;
  padding: 0;
  width: 39%;
  color: #606266;
  line-height: 1;
  height: 100%;
  margin: 0;
  text-align: center;
  display: inline-block;}
.yearPicker {
  // font-size: 14px;
  // display: flex;
  // position: relative;
  // transition: all 0.3s;
  input:first-child {
    text-align: right;}
  .labelText {
    position: absolute;
    left: 8px;}
  background-color: #fff;
  span {
    padding: 0 8px;
    height: 32px;
    line-height: 32px;}
  border: 1px solid #eff1f3;
  height: 34px;
  line-height: 34px;
  border-radius: 4px;
  padding: 0 28px 0 8px;
  box-sizing: border-box;}
input {
  width: 60px;
  border: none;
  height: 32px;
  line-height: 32px;
  box-sizing: border-box;
  background-color: transparent;}
input:focus {
  outline: none;
  background-color: transparent;}
.yearPicker:hover {
  border-color: #3e77fc;}
.dateIcon {
  position: absolute;
  right: 16px;
  top: 9px;
  color: #adb2bc;}</style>

yearDate.js文件

export const clickoutside ={
  bind(el, binding, vnode){function documentHandler(e){
      // 这里判断点击的元素是否是本身,是本身,则返回
      if(el.contains(e.target)){returnfalse}
      // 判断指令中是否绑定了函数
      if(binding && binding.expression){
        // 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法
        if(binding.value && binding.value(e)){
          binding.value(e)}}}
    // 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听
    el.__vueClickOutside__ = documentHandler
    document.addEventListener('click', documentHandler)},
  unbind(el, binding){
    // 解除事件监听
    document.removeEventListener('click', el.__vueClickOutside__)
    delete el.__vueClickOutside__
  }}export const SELECT_STATE ={
  unselect: 0,
  selecting: 1,
  selected: 2}

我是禁止了未来日期,时间跨度,只能选3年,
代码如下:

<template><el-popover
    ref="popover"placement="bottom"
    v-model="showPanel"
    popper-class="custom_year_range"trigger="manual"
    v-clickoutside="() => { showPanel = false }"><div class="_inner floatPanel"><div class="_inner leftPanel"><div class="_inner panelHead"><i
            class="_inner el-icon-d-arrow-left"
            @click="onClickLeft"></i><span>{{ leftYearList[0] + '年 ' + '- ' + leftYearList[9] + '年'}}</span></div><div class="_inner panelContent"><div
            :class="{
              oneSelected: item === startYear && oneSelected,
              startSelected: item === startYear,
              endSelected: item === endYear,
              betweenSelected: item > startYear && item < endYear,
            }"
            v-for="item in leftYearList"
            :key="item"><a
            v-if="item > disabledDate || ( curState === 1 && (item < curSelectedYear-spanNumber  || item > curSelectedYear+spanNumber))"
              :class="{
                cell: true,
                _inner: true,
                disabled:true
              }">{{ item }}</a><a
            v-else
              :class="{
                cell: true,
                _inner: true,
                selected: item === startYear || item === endYear,
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div><div class="_inner rightPanel"><div class="_inner panelHead"><i
            class="_inner el-icon-d-arrow-right"
            @click="onClickRight"></i><span>{{ rightYearList[0] + '年 ' + '- ' + rightYearList[9] + '年'}}</span></div><div class="_inner panelContent"><div
            :class="{
              startSelected: item === startYear,
              endSelected: item === endYear,
              betweenSelected: item > startYear && item < endYear,
            }"
            v-for="item in rightYearList"
            :key="item"><a
            v-if="item > disabledDate || ( curState === 1 && (item < curSelectedYear-spanNumber  || item > curSelectedYear+spanNumber))"
              :class="{
                cell: true,
                _inner: true,
                disabled:true
              }">{{ item }}</a><a v-else
              :class="{
                cell: true,
                _inner: true,
                selected: item === endYear || item === startYear,
              }"
              @click="onClickItem(item)"
              @mouseover="onHoverItem(item)">{{ item }}</a></div></div></div></div><div slot="reference"><div
        ref="yearPicker"style="width: 100%"class="el-date-editor el-range-editor el-input__inner el-date-editor--daterange el-range-editor--small"><i class="el-input__icon el-range__icon el-icon-date"></i><input
          class="_inner range_input"ref="inputLeft"type="text"name="yearInput"placeholder="选择开始年份"
          v-model="startShowYear"
          :editable="false"
          :clearable="false"
          @focus="onFocus"
          @keyup="handleInput('start')"
        /><span class="el-range-separator">{{ sp }}</span><input
          class="_inner range_input"ref="inputRight"type="text"name="yearInput"placeholder="选择结束年份"
          v-model="endShowYear"
          :editable="false"
          :clearable="false"
          @focus="onFocus"
          @keyup="handleInput('end')"
        /></div></div></el-popover></template><script>import moment from 'moment'import{ clickoutside, SELECT_STATE } from './yearDate.js'export default {
  name: 'yearPicker',
  directives: { clickoutside },
  computed: {oneSelected(){return this.curState === SELECT_STATE.selecting &&(this.startYear === this.endYear || this.endYear == null)},
    leftYearList(){return this.yearList.slice(0, 10)},
    rightYearList(){return this.yearList.slice(10, 20)},
  },
  props: {
    sp: {
      default: '至'},
    value: {
      default: null
    }},
  data(){return{
      disabledDate:new Date().getFullYear(),//禁止未来日期
      spanNumber:2, //可选择的跨度最大数
      disabledYear:null,
      itemBg: {},
      startShowYear: null,
      endShowYear: null,
      yearList: [],
      showPanel: false,
      startYear: null,
      endYear: null,
      curYear: 0,
      curSelectedYear: 0,
      curState: SELECT_STATE.unselect
    }},
  methods: {
    handleInput(type){
      switch (type){case'start':if(isNaN(this.startShowYear)){
            this.startShowYear = this.startYear
            return}
          this.startYear = this.startShowYear * 1breakcase'end':if(isNaN(this.endShowYear)){
            this.endShowYear = this.endYear
            return}
          this.endYear = this.endShowYear * 1break}[this.startYear, this.endYear]=[this.endYear, this.startYear]
      this.startShowYear = this.startYear
      this.endShowYear = this.endYear
    },

    onHoverItem(iYear){if(this.curState === SELECT_STATE.selecting){
        const tmpStart = this.curSelectedYear
        this.endYear = Math.max(tmpStart, iYear)
        this.startYear = Math.min(tmpStart, iYear)
        this.disabledYear = iYear
      }},

    async onClickItem(selectYear){if(
        this.curState === SELECT_STATE.unselect ||
        this.curState === SELECT_STATE.selected
      ){
        this.startYear = selectYear
        this.curSelectedYear = selectYear
        this.endYear = null
        this.curState = SELECT_STATE.selecting
      }elseif(this.curState === SELECT_STATE.selecting){
        this.endShowYear = this.endYear || this.startYear
        this.startShowYear = this.startYear
        this.curState = SELECT_STATE.selected
        await this.$nextTick()
        this.showPanel =false
        this.$parent?.$parent?.$parent?.$parent?.$parent.clearValidate?.()}},

    async onFocus(){
      await this.$nextTick()
      this.showPanel =true},

    updateYearList(){
      const startYear = ~~(this.curYear / 10) * 10
      this.yearList =[]for(let index =0; index <20; index++){
        this.yearList.push(startYear + index)}},

    onClickLeft(){
      this.curYear = this.curYear * 1 - 10
      this.updateYearList()},

    onClickRight(){
      this.curYear = this.curYear * 1 + 10
      this.updateYearList()}},
  watch: {
    value: {
      handler(val){if(val?.length ===0)return
        const [first, end]= val ||[]
        this.startShowYear = first
        this.endShowYear = end
      },
      immediate: true,
      deep: true},

    startShowYear: {
      handler(val){
        this.$emit('input', [val, this.endShowYear ||''])},
      immediate: true,
      deep: true},

    endShowYear: {
      handler(val){
        this.$emit('input', [this.startShowYear ||'', val])},
      immediate: true,
      deep: true}},
  created(){
    const [startYear, endYear]= this.value ||[]if(startYear){
      this.startYear = Number(startYear)
      this.endYear = Number(endYear)
      this.curState = SELECT_STATE.selected
      this.curYear = startYear
    }else{
      this.curYear = moment().format('yyyy')}
    this.updateYearList()},

  mounted(){
    window.Vue = this
  }}</script><style lang="scss">
.custom_year_range {
  .floatPanel {> div {
      width: 50%;}
    padding: 0 16px;
    // position: absolute;
    display: flex;
    background-color: #fff;
    z-index: 2000;
    border-radius: 4px;
    width: 650px;
    height: 250px;
    top: 40px;
    left: -50px;
    .panelContent {
      display: flex;
      flex-wrap: wrap;
      width: 100%;
      height: calc(100% - 70px);
      .oneSelected {
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;}
      .startSelected {
        background-color: #f2f6fc;
        border-top-left-radius: 24px;
        border-bottom-left-radius: 24px;}
      .endSelected {
        background-color: #f2f6fc;
        border-top-right-radius: 24px;
        border-bottom-right-radius: 24px;}
      .betweenSelected {
        background-color: #f2f6fc;}> div {
        width: 75px;
        height: 48px;
        line-height: 48px;
        margin: 3px 0;
        // border-radius: 24px;
        text-align: center;
        a {
          display: inline-block;
          width: 60px;
          height: 36px;
          cursor: pointer;
          line-height: 36px;
          border-radius: 18px;&:hover {
            color: #409eff;}}
        .selected {
          background-color: #409eff;
          color: #fff;&:hover {
            color: #fff !important;}}}}
    .panelHead {
      position: relative;
      height: 46px;
      line-height: 46px;
      text-align: center;
      display: flex;
      align-items: center;
      justify-content: center;
      span {
        font-size: 16px;
        font-weight: 500;
        padding: 0 5px;
        line-height: 22px;
        text-align: center;
        cursor: pointer;
        color: #606266;&:hover {
          color: #409eff;}}
      i {
        position: absolute;
        cursor: pointer;&:hover {
          color: #3e77fc;}}}
    .rightPanel {
      padding-left: 8px;}
    .leftPanel .panelHead i {
      left: 20px;}
    .rightPanel .panelHead i {
      right: 20px;}}
  .floatPanel::before {
    content: "";
    height: 100%;
    top: 0;
    position: absolute;
    left: 50%;
    width: 1px;
    border-left: 1px solid #e4e4e4;}}</style><style lang="scss" scoped>
.range_input {
  appearance: none;
  border: none;
  outline: 0;
  padding: 0;
  width: 39%;
  color: #606266;
  line-height: 1;
  height: 100%;
  margin: 0;
  text-align: center;
  display: inline-block;}
.yearPicker {
  // font-size: 14px;
  // display: flex;
  // position: relative;
  // transition: all 0.3s;
  input:first-child {
    text-align: right;}
  .labelText {
    position: absolute;
    left: 8px;}
  background-color: #fff;
  span {
    padding: 0 8px;
    height: 32px;
    line-height: 32px;}
  border: 1px solid #eff1f3;
  height: 34px;
  line-height: 34px;
  border-radius: 4px;
  padding: 0 28px 0 8px;
  box-sizing: border-box;}
input {
  width: 60px;
  border: none;
  height: 32px;
  line-height: 32px;
  box-sizing: border-box;
  background-color: transparent;}
input:focus {
  outline: none;
  background-color: transparent;}
.yearPicker:hover {
  border-color: #3e77fc;}
.dateIcon {
  position: absolute;
  right: 16px;
  top: 9px;
  color: #adb2bc;}
.disabled{
    background-color: #F5F7FA;
    cursor: not-allowed;
    color: #606266;
    border-radius: 18px;&:hover {
          cursor: not-allowed!important;
          color: #606266!important;}}</style>

参考地址:https://www.jianshu.com/p/44584a4a4953

标签: vue.js elementui

本文转载自: https://blog.csdn.net/xingchen678/article/details/128914174
版权归原作者 xingchen678 所有, 如有侵权,请联系我们删除。

“vue element-ui年份范围选择器,年日期插件,可选日期区间等”的评论:

还没有评论