Vue - Secondary encapsulation of the Vant calendar component (calendar) in vue

The secondary encapsulation of the vant calendar selector component in vue; the main functions are as follows:

The main function:

  1. date range selection (basic);
  2. Customize the bottom button of the selector, add a clear time operation (slot slot);
  3. Specify the date range selected by default (current date to the end of this month via default-date)
  4. Custom date optional range; (via min-date and max-date)
  5. Support the import of default values; (placeholder will be displayed when there is no default value: please select a time interval)
  6. Customize the width of the component; (through props:Width, it is recommended to use a percentage such as: 80%)

The renderings are as follows:
Please add a picture description

The date interval component is implemented as follows: calendar.vue

Main code explanation:

1. By <template slot="footer">changing the default button at the bottom, I added a 清除时间button here; clicking 清除时间the button will clear the time and restore it to the default state;
2. By min-date 和 max-datecontrolling the range of the start and end of the date;
3. Through default-datethe Change the date range specified by default. It should be noted that the return is an array, the start position and the end position; you can take a look at the timeInterval() method; 4. Click the confirm button onConfirmAll() to return the selected start date
and end date To the parent component; the time format is as follows: 2023-02-20;
5, you can pass in the defaultData default value, if there is no default value, it will be displayed: 请选择时间区间;
6, you can pass in :Width="'100%'"to control the width of the component;
7, you can make corresponding changes to the current component according to different business needs adjustment;

<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>

In the parent component use:

<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>

Guess you like

Origin blog.csdn.net/qq_43886365/article/details/129127966