vue3封装年份组件

发布时间:2023年12月20日

ant框架年份组件
看了ant框架针对于年份不能自定义插槽内容所以放弃用ant框架年份组件,自定义插槽内容是想实现年份下方可以加小圆点的需求,因加小圆点需求必须实现,决定自己封装组件来实现需求,自己实现的效果呢类似于ant年份控件 在这里做一下记录。
效果图如下:
在这里插入图片描述
1.YearPicker.vue

<template>
  <div class="year-picker" >
    <q-input
      outlined
      v-model="contentValue"
      dense
      @blur="blurEvent"
      @focus="inputFocus"
      placeholder="选择年份"
      clearable
      @clear="clearHandle"
      class="col"
    >
    </q-input>
    <transition name="fade">
      <div class="year-picker__year-box" v-if="showYearContent">
        <div class="year-picker__year-title">
          <span class="to-left" @click="toLeft()"><DoubleLeftOutlined style="rgba(0, 0, 0, 0.45)"/></span>
          <span class="to-middle">{{yearStart}}-{{yearEnd-1}}</span>
          <span class="to-right" @click="toRight()"><DoubleRightOutlined style="rgba(0, 0, 0, 0.45)"/></span>
        </div>
        <div class="year-picker__year-content" >
         <span v-for="(item,index) in yearList" :key="index" style="position: relative;">
          <div  class="listItem" :class="{listItemBgC: item === checkedIndex,'year-disable':yearDis(item)}" @click="chooseYear(item,index)">{{item}}</div>
           <div :class="getAllYear(item)" ></div>
         </span>
        </div>
      </div>
    </transition>
  </div>
</template>
<script>
import { ref, shallowRef, watch, nextTick, onMounted, inject,reactive ,computed,toRefs,getCurrentInstance,watchEffect} from 'vue'
import {DoubleLeftOutlined,DoubleRightOutlined} from '@ant-design/icons-vue'
export default {
  name: 'index',
  components:{
    DoubleLeftOutlined,
    DoubleRightOutlined
  },
  props: {
    yearDisable: {
      type: String,
      default: 'no'
    },
    contentValue: {
      type: Number,
    },
    allDataList:{
      type: Array,
      default: ()=>{
        return []
      }
    },
  },
  setup(props,context) {

    const { yearDisable } = toRefs(props);

    const checkedIndex = ref()

    const state = reactive({
      yearLists: [],
      showYearContent: false,
      yearStart: 2010,
      yearEnd: 2030,
      blurIndex:null,
      allDataList:[],
    })

    const contentValue = ref()

    watch(() => props.contentValue, (newvalue) => {
      if(newvalue){
        contentValue.value = newvalue
        context.emit('handlerInput',newvalue)
      }
    }, {immediate: true})

    watch(() => props.allDataList, (value) => {
      if(!value) return
      state.allDataList = value
    }, {immediate: true})

    const inputFocus = ()=> {
      state.showYearContent = true
    }

    const blurEvent= (e)=> {
      state.showYearContent = false
    }

    const chooseYear=(year,index)=> {
      if (year > yearDis.value) return
      state.showYearContent = false
      checkedIndex.value = year
      context.emit('handlerInput', year)
    }

    const toLeft=()=> {
      state.yearStart -= 20
      state.yearEnd -= 20
      state.showYearContent = true
    }

    const toRight=()=> {
      state.yearStart += 20
      state.yearEnd += 20
      state.showYearContent = true
    }

    const yearDis = computed(()=>{
      return function (y) {
        switch (yearDisable.value) {
          case 'before': {
            return y < new Date().getFullYear()
          }
            break;
          case 'no': {
            return false
          }
            break;
          case 'after': {
            return y > new Date().getFullYear()
          }
        }
      }
    })

    const yearList = computed(()=>{
      let arr = []
      for (let i = state.yearStart; i < state.yearEnd; i++) {
        arr.push(i)
      }
      return arr
    })

    const clearHandle = (value)=>{
      checkedIndex.value = ''
    }
	
	//实现年份下方加小圆点事件
    const getAllYear = (year) => {
      if(state.allDataList.findIndex(mon =>  mon === year) !== -1){
        return 'checkbox1'
      }else{
        return 'defultbox1'
      }
    }

    return {
      ...toRefs(state),
      yearDis,
      getAllYear,
      yearList,
      checkedIndex,
      clearHandle,
      inputFocus,
      contentValue,
      blurEvent,
      chooseYear,
      toLeft,
      toRight,
    }
  },
}
</script>

<style scoped lang="scss">
.checkbox1{
  position: absolute;
  left: 50%;
  height: 5px;
  width: 8px;
  border-radius: 5px;
  background-color: #ff9800;
  transform: translate3d(-50%,0,0)
}
.defultbox1{
  position: absolute;
  left: 50%;
  height: 5px;
  width: 8px;
  border-radius: 5px;
}
.year-picker {
  ::v-deep(.q-field--dense .q-field__control){
    height: 32px!important;
  }
  ::v-deep(.q-field--dense .q-field__marginal){
    height: 32px!important;
  }

  .col{
    box-sizing: border-box;
    margin: 0;
    color: rgba(0, 0, 0, 0.88);
    font-size: 14px;
    height: 32px!important;
    position: relative;
    display: inline-flex;
    align-items: center;
    background: #ffffff;
    border-radius: 6px;
    transition: border 0.2s,box-shadow;
  }
  .col:hover{
    border: none!important;
    margin: 0;
  }

  margin-left: 20px;
  display: inline-block;
  border-radius: 5px;
  .year-picker__icon {
    position: absolute;
    transform: translate(-26px, 10px);
    color: #d9d9d9
  }
  .year-picker__input--real:hover {
    border: 1px solid rgba(0, 122, 244, 0.8);
  }

  .year-picker__year-title {
    height: 40px;
    width: 270px;
    border-top: 1px solid #d4d4d4;
    border-bottom: 1px solid #d4d4d4;
    display: flex;
    justify-content: space-around;
    align-items: center;
    .to-middle{
      font-weight: bold;
      color: #666666;
    }
    span {
      color: #525252;
      cursor: pointer;
    }

    span:active {
      opacity: .5;
    }
  }

  .year-picker__year-box {
    position: absolute;
    z-index: 10;
    background: #ffffff;
    border-radius: 5px;
    border: 1px solid #eeeeee;
    box-shadow: 0 0 .38rem 0 rgba(0, 0, 0, 0.1);
    transform: translateY(-32px);
    left:36px;
    top:72px;
  }
  .year-picker__year-content {
    padding-top: 20px;
    width: 270px;
    height: 250px;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    .listItem{
      color: #525252;
      font-size: 14px;
      width: 48px;
      height: 25px;
      display: flex;
      justify-content: center;
      align-items: center;
      margin-bottom: 2px;
    }
    .listItem:hover{
      cursor: pointer;
    }
    .listItemBgC{
      background-color: #0067c0;
      color:white;
      border-radius: 3px;
    }
    .year-disable {
      background: #f5f5f5;
    }
    .year-disable:hover {
      cursor: no-drop;
      background: #f5f5f5;
    }
  }
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
  transform: translateY(-30px);
}
/* 过程 */
.fade-enter-active {
  transition: all 0.5s;
}
/* 结束 */
.fade-enter-to {
  opacity: 1;
}
.fade-leave-active {
  transition: all 0.5s;
}

.dark {
  border: 1px solid blue;
  color: #8099b3;

  .year-picker__input {
    background: #003366;
    color: #8099b3;;
  }

  .year-picker__input--real {
    border: 1px solid blue;
    height: 32px;
  }

  .year-picker__input::placeholder {
    color: #1c5389;
  }

  .year-picker__year-title {
    border-top: 1px solid blue;
    border-bottom: 1px solid blue;

    span {
      color: #8099b3;
    }
  }

  .year-text:hover {
    cursor: pointer;
    background: rgba(157, 219, 252, 0.41);
    border-radius: 3px;
  }

  .year-picker__year-content {
    .year-text {
      color: #8099b3;
    }

    .year-disable {
      background: #133558;
    }

    .year-disable:hover {
      cursor: no-drop;
      background: #133558;
    }
  }
}
</style>


vue 使用组件

 <YearPicker :contentValue="contentValue" @handlerInput="handlerInput" :year-disable="'no'" :allDataList="allDataList"/>
 const state =  reactive({
      contentValue:'', //选中的年份
      allDataList:[2018,2019],// 加这个属性呢是实现年份下方加黄色小圆点
 })
 //组件里选中的年份传过来的事件
 const handlerInput =  (value) =>{
     console.log(value)
    state.contentValue = value
  }

文章来源:https://blog.csdn.net/Yujis/article/details/135107531
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。