vue - vue中对Vant日历组件(calendar)的二次封装

vue中对vant日历选择器组件实现的的二次封装;主要实现功能如下:

主要功能:

  1. 日期区间选择(基本);
  2. 自定义选择器的底部按钮,添加清除时间操作(slot插槽);
  3. 指定默认选中的日期范围(当前日期到本月底通过default-date)
  4. 自定义日期可选范围;(通过 min-date 和 max-date )
  5. 支持默认值的传入;(没有默认值时会显示placeholder:请选择时间区间)
  6. 自定义组件的宽度;(通过props:Width,推荐使用百分比 如:80%)

效果图如下:
请添加图片描述

日期区间组件实现如下:calendar.vue

主要代码讲解:

1, 通过<template slot="footer">可以更改底部默认的按钮,我这边添加来了一个清除时间的按钮;点击清除时间按钮会把时间清空,恢复到默认状态;
2,通过min-date 和 max-date控制日期可以选择的开始和结束的范围;
3,通过default-date可以更改指定默认选中的日期范围,需要注意的是返回的是一个数组,开始位置和结束位置;可以看一下timeInterval()方法;
4,点击确认按钮onConfirmAll()会把所选择开始日期和结束日期返回给父组件;时间格式如下:2023-02-20
5,可以传入defaultData 默认值,没有默认值会显示: 请选择时间区间
6,可以传入:Width="'100%'" 来控制组件的宽度;
7,针对不同的业务需求可以对当前组件做出相应的调整;

<template>
  <!-- 日期选择组件 可指定选择范围 -->
  <div class="calendar" :style="`width:${Width}`">
    <van-field :label="title" v-model="date" right-icon="arrow-down" readonly @click="show = true" :placeholder="placeholder" />
    <!-- 日期选择器 -->
    <van-calendar safe-area-inset-bottom v-model="show" color="#1989fa" type="range" @confirm="onConfirm" :min-date="minDate" :max-date="maxDate" :default-date="timeInterval()" ref="myCalendar">
      <template slot="footer">
        <div class="footer">
          <van-button @click="clearTimeAll" type="danger" class="footerBtn">清除时间</van-button>
          <van-button class="footerBtn" @click="onConfirmAll" type="info">确认</van-button>
        </div>
      </template>
    </van-calendar>
  </div>
</template>

<script>
export default {
    
    
  name: 'calendar',
  components: {
    
    },
  props: {
    
    
    /*  可以不用传  用来展示左侧的文案  为空则不展示文案*/
    title: {
    
    
      type: String,
      default: '',
    },
    /* 传过来的默认值 */
    defaultData: {
    
    
      type: String,
      // default:'请选择'
    },
    placeholder: {
    
    
      type: String,
      default: '请选择时间区间',
    },
    // 宽度
    Width: {
    
    
      type: String,
    },
  },
  data() {
    
    
    return {
    
    
      date: this.defaultData ? this.defaultData : '', // 先判断有没有默认值 有就用没有就为空
      show: false,
      // 日期区间
      minDate: new Date(2022, 0, 1),
      maxDate: new Date(2025, 12, 31),

      // 当前日期
      currentDate: new Date().getDate(),
    };
  },
  computed: {
    
    },
  watch: {
    
    
    // 监听到需要重新赋值
    defaultData(newValue) {
    
    
      this.date = newValue;
    },
  },
  created() {
    
    
    // 处理默认值 如果有默认值直接赋值
    if (this.defaultData) {
    
    
      this.date = this.defaultData;
    }
  },
  mounted() {
    
    },
  methods: {
    
    
    /* 日期区间 当前自动选择的日期区间 :取当天到月底   返回的是一个数组*/
    timeInterval() {
    
    
      let new_year = new Date().getFullYear();
      let new_month = new Date().getMonth() + 1;
      let new_date = new Date(new_year, new_month, 1); //取当年当月中的第一天
      let end = new Date(new_date.getTime() - 1000 * 60 * 60 * 24); //取最后一天
      return [new Date(), end];
    },

    /* 确认选择 组件自带的事件 */
    onConfirm(date) {
    
    
      const [start, end] = date;
      this.show = false;
      this.date = `${
      
      this.formatDate(start)} - ${
      
      this.formatDate(end)}`;
      // 传给父组件 以此来请求数据
      this.$emit('dateFun', `${
      
      this.formatDate(start)}`, `${
      
      this.formatDate(end)}`);
    },

    /* 确认按钮 */
    onConfirmAll() {
    
    
      // 直接调用上面的方法
      if (this.$refs.myCalendar) {
    
    
        this.$refs.myCalendar.onConfirm();
      } else {
    
    
        console.warn('myCalendar实例没有获取到');
      }
    },

    /* 清除时间 时间置空*/
    clearTimeAll() {
    
    
      this.date = '';
      this.show = false;
      this.$emit('dateFun', ``, ``);
    },
    /* 转换时间 */
    formatDate(date) {
    
    
      // 给日期补0
      return `${
      
      date.getFullYear()}-${
      
      (date.getMonth() + 1).toString().padStart(2, '0')}-${
      
      date.getDate().toString().padStart(2, '0')}`;
    },
  },
};
</script>

<style scoped lang="scss">
// 覆盖 van-field的样式
/deep/ .van-cell {
    
    
  padding: 2px 5px;
  border-radius: 5px;
  border: 1px solid #1457f0;
}
/deep/ .van-field__right-icon {
    
    
  margin-right: 0;
  padding: 0;
  color: #1457f0;
}
.footer {
    
    
  display: flex;
  justify-content: space-between;
  align-items: center;

  // 底部自定义按钮的样式
  .footerBtn {
    
    
    width: 150px;
    border-radius: 2px;
  }
}
</style>

父组件中使用:

<template>
  <div>
    <!-- 日期区间选择器演示 -->
    <h4>Vant日期区间选择器封装</h4>
    <div class="Calendar">
      <Calendar @dateFun="dateFun" :Width="'80%'" :defaultData="defaultData"></Calendar>
    </div>
  </div>
</template>

<script>
// 时间选择器
import Calendar from '../../components/calendar/calendar.vue';
export default {
    
    
//注册
  components: {
    
     Calendar },
  data() {
    
    
    return {
    
    
    	// 组件的默认值  没有可以为空 或者 组件中不在使用defaultData属性
      	defaultData:'2023-01-01-2023-02-01',
      ],
    };
  },
  methods: {
    
    
  	//接收子组件传过来的日期值 
    dateFun(start, end) {
    
    
      console.log('start:', start, 'end:', end);
      
      // 保存获取到的时间...
    },
  },
};
</script>

<style scoped lang="scss">
.Calendar {
    
    
  margin-top: 20px;
}
</style>

猜你喜欢

转载自blog.csdn.net/qq_43886365/article/details/129127966
今日推荐