封装组件库-时间选择器

2023, Mar 01    

实现时间选择器的封装

基于Element-plus框架的TimeSelect时间选择组件和DatePicker日期选择器组件,封装为时间选择器和日期选择器。

初始配置

  • 注册路由组件chooseTime,配置为Container组件的子路由组件
  • 采用路由懒加载,箭头函数异步引入组件。
  • 注册通用组件chooseTime,为路由组件的子组件,以便组件间通信。
  • 将通用组件chooseTime注册为全局组件

时间选择器组件

  • 子组件
    <!-- 传参及类型 -->
    let props = defineProps({
        //开始时间占位符
        startPlaceholder:{
            type: String,
            default: '请选择开始时间'
        },
        //开始时间的初始化
        startTimeStart: {
            type: String,
            default: '08:00'
        },
        //开始时间的步进
        startStep: {
            type: String,
            default: '00:30'
        },
        //开始时间的结束
        startTimeEnd: {
            type: String,
            default: '24:00'
        },
        //结束时间占位符
        endPlaceholder:{
            type: String,
            default: '请选择结束时间'
        },
        //结束时间的初始化
        endTimeStart: {
            type: String,
            default: '08:00'
        },
        //结束时间的步进
        endStep: {
            type: String,
            default: '00:30'
        },
        //结束时间的结束
        endTimeEnd: {
            type: String,
            default: '24:00'
        }
    })
      //开始时间
      let startTime = ref<string>('')
      //结束时间
      let endTime = ref<string>('')
      //结束时间的禁用
      let endTimeDisabled = ref<boolean>(true)
  • 绑定
  <el-time-select
    v-model="startTime"
    :max-time="endTime"
    class="mr-4"
    :placeholder="startPlaceholder"
    :start="startTimeStart"
    :step="startStep"
    :end="startTimeEnd"
    //未配置props的传参,经过attrs并分类
    v-bind="$attrs.startOptions"
    />
  <el-time-select
    v-model="endTime"
    :min-time="startTime"
    :placeholder="endPlaceholder"
    :start="endTimeStart"
    :step="endStep"
    :end="endTimeEnd"
    :disabled="endTimeDisabled"
    v-bind="$attrs.endOptions"
    />
  • 实现联动效果,并向父组件分发事件
  //监听开始时间的变化  
  watch(()=>startTime.value,val=>{
      //未选择或删除开始时间,则将结束时间置空,并禁用结束时间
      if(val === '') {
          endTime.value = ''
          endTimeDisabled.value = true
      }
      //开始时间变化,开启结束组件,并向父组件传递开始时间
      else{
          endTimeDisabled.value = false
          //给父组件分发事件
          emits('startChange',val)
      }
  })
  
  //监听结束时间的变化
  watch(()=>endTime.value,val=>{
      //选择结束时间则向父组件传递一个对象,包含开始和结束时间
      if(val !== ''){
          emits('endChange',{
              startTime: startTime.value,
              endTime: endTime.value
          })
      }
  })
  • 父组件
  <my-choose-time 
    @startChange="startChange" 
    @endChange="endChange"
    :startOptions="startOptions"
    >
  //可配置剩余项  
  let startOptions= {
    size: 'default',
    clearable: false
  }

日期选择器组件

  • 定义chooseDate组件,并进行全局注册
  <!-- 传参及类型 -->
  let props = defineProps({
    //开始时间占位符
    startPlaceholder:{
        type: String,
        default: '请选择开始日期'
    },   
    //结束时间占位符
    endPlaceholder:{
        type: String,
        default: '请选择结束日期'
    },
    //是否禁用选择今天之前的日期
    disableToday: {
        type: Boolean,
        default: true
    } 
  })
  
  let startDate = ref<Date | null>(null)
  let endDate = ref<Date | null>(null)
  //控制结束日期的禁用状态
  let endDateDisabled = ref<boolean>(true)
  • 开始日期对今天以前的日期进行禁用
  let startDisabledDate = (time: Date)=>{
    //对日期小于当前时间 - 一天的日期禁用
    if(props.disableToday) return time.getTime() < Date.now() - 1000 * 60 * 60 * 24
  }
  
  <el-date-picker :disabled-date="startDisabledDate"/>
  let endDisabledDate = (time: Date)=>{
    if(startDate.value) { 
        return time.getTime() < startDate.value.getTime() + 1000 * 60 * 60 * 24
    }
  }
  //结束组件
  <el-date-picker :disabled-date="endDisabledDate"/>
  • 联动效果设计
  //监听开始日期
  watch(()=>startDate.value,val=>{
      //未选择开始日期或删除,则禁用结束组件并清空
      if(!val){
          endDateDisabled.value = true
          endDate.value = null
      }else{
          //选择开始日期则向父组件传递开始日期,解禁结束组件
          endDateDisabled.value = false
          emits('startChange',val)

      }
  })
  
  //监听结束日期
  watch(()=>endDate.value,val=>{
      //选择结束日期,则向父组件传递对象,包含开始日期和结束日期
      if(val){
          emits('endChange',{
              startDate: startDate.value,
              endDate: endDate.value
          })         
      }
  })
  • 父组件
   <my-choose-date @startChange="dateStartChange" @endChange="dateEndChange" :endOptions="endOptions">
   //示例,为结束组件配置 $attrs.endOptions进行接收
   let endOptions= {
    size: 'default',
    clearable: false
   }