文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue怎么实现左右滑动选择日期组件

2023-06-29 21:35

关注

今天小编给大家分享一下vue怎么实现左右滑动选择日期组件的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

效果图:

vue怎么实现左右滑动选择日期组件

1、安装dayjs日期文件

npm install dayjs --save

2、封装的组件:

<template>  <div class="m-calendar" ref="calendar">    <div class="m-toolbar">      <div class="m-year-selector">        <!-- <a class="m-prev-btn" @click="changeYear('prev')"></a> -->        <span>{{showDate.year}}{{yearName}}</span>        <!-- <a class="m-next-btn" @click="changeYear('next')"></a> -->      </div>      <div class="m-month-selector">        <!-- <a class="m-prev-btn" @click="changeMonth('prev')"></a> -->        <span>{{monthNames[showDate.month-1]}}</span>        <!-- <a class="m-next-btn" @click="changeMonth('next')"></a> -->      </div>    </div>    <div class="m-week-header">      <div        class="m-week-day"        v-for="item in weekNames"        :key="item"      >        {{item}}      </div>    </div>    <div      class="m-months-container"      @touchstart="touchstart"      @touchmove="touchmove"      @touchend="touchend"    >      <div        class="m-months-wrapper"        :      >        <div          class="m-months"          v-for="(month,monthIndex) in fullDate"          :key="monthIndex"          :style="{            transform: `translate3d(${(monthIndex-1+translateX + (isTouching ? touch.x : 0))*100}%, 0, 0)`,            transitionDuration: isTouching ? '0s' : '.3s',          }"        >          <div            class="m-row"            v-for="(week,weekIndex) in month"            :key="weekIndex"          >            <div              class="m-day"              v-for="(day,dayIndex) in week"              :key="dayIndex"              @click="onDayClick(day)"            >              <span                :class="{                  'm-day-num':true,                  'm-grey': day.isGrey,                  'm-today': day.isToday,                  'm-disable': day.isDisable,                  'm-select': day.isSelect,                }"              >                  <!-- 'm-during': day.isDuring -->                {{day.value}}              </span>              <slot name="day" :date="day" />            </div>          </div>        </div>      </div>    </div>  </div></template><script>import dayjs from 'dayjs';let touchStartPosition;let touchEndPosition;let timeStamp;export default {  name: 'inlineCalendar',  props: {    defaultDate: {      type: [Date, Number, Array, String, dayjs],    },    disabledDate: {      type: Array,      default() {        return [];      },    },    minDate: {      type: [Date, Number, Array, String, dayjs],    },    maxDate: {      type: [Date, Number, Array, String, dayjs],    },    mode: {      type: String,      default: 'single',    },    dayClick: {      type: Function,      default() {        return function() {          return true;        };      },    },    enableTouch: {      type: Boolean,      default: true,    },    monthNames: {      type: Array,      default() {        return ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'];      },    },    weekNames: {      type: Array,      default() {        return ['一', '二', '三', '四', '五', '六', '日'];      },    },    yearName: {      type: String,      default: '年',    },    restrictCurrentMonth: {      type: Boolean,      default: false,    },  },  watch: {    mode() {      this.init();    },  },  data() {    return {      fullDate: [[], [], []],      translateX: 0,      showDate: {        year: undefined,        month: undefined,      },      dateNow: {        year: dayjs().year(),        month: dayjs().month() + 1,        date: dayjs().date(),      },      selectDate: [],      touch: {        x: 0,        y: 0,      },      isTouching: false,    };  },  created() {    this.init();  },  methods: {    init(date) {      this.selectDate = [];      let { defaultDate, mode } = this;      if (date) {        defaultDate = date;      }      let dateToShow = dayjs().startOf('month');      if (mode === 'single' && defaultDate) {        this.selectDate = dayjs(defaultDate).startOf('day');        dateToShow = this.selectDate.startOf('month');      }      if (mode === 'multiple' && Array.isArray(defaultDate)) {        if (defaultDate.length > 0) {          this.selectDate = defaultDate.map((item) => dayjs(item).startOf('day'));        }      }      if (mode === 'during' && Array.isArray(defaultDate)) {        if (defaultDate.length === 2) {          const startDate = dayjs(defaultDate[0]).startOf('day');          const endDate = dayjs(defaultDate[1]).startOf('day');          if (startDate.isBefore(endDate) || startDate.isSame(endDate)) {            this.selectDate = [startDate, endDate];          }        }      }      this.showDate = {        year: dateToShow.year(),        month: dateToShow.month() + 1,      };      this.getFullDate(this.showDate);    },    touchstart(event) {      if (this.enableTouch) {        touchStartPosition = event.touches[0].clientX;        touchEndPosition = event.touches[0].clientY;        timeStamp = event.timeStamp;        this.touch = {          x: 0,          y: 0,        };        this.isTouching = true;      }    },    touchmove(event) {      if (this.enableTouch) {        this.touch = {          x: (event.touches[0].clientX - touchStartPosition) / this.$refs.calendar.offsetWidth,          y: (event.touches[0].clientY - touchEndPosition) / this.$refs.calendar.offsetHeight,        };      }    },    touchend(event) {      if (this.enableTouch) {        this.isTouching = false;        const during = dayjs(event.timeStamp).diff(timeStamp);        if (Math.abs(this.touch.x) > Math.abs(this.touch.y) && Math.abs(this.touch.x * this.$refs.calendar.offsetWidth) > 20) {          if (this.touch.x > 0) {            this.changeMonth('prev');          } else if (this.touch.x < 0) {            this.changeMonth('next');          }        } else {          this.touch = {            x: 0,            y: 0,          };        }      }    },    // 触发change事件    emitChange() {      this.$emit('change', this.selectDate);    },    // 触发切换年月事件    emitSwitch(showDate) {      if (this.restrictCurrentMonth) {        this.selectDate = [];      }      this.$emit('switch', showDate);    },    // 日期点击事件    onDayClick(day) {      if (!this.dayClick(day.dateTime)) {        return;      }      switch (this.$props.mode) {      case 'single':        if (!day.isSelect && !day.isDisable) {          this.selectDate = day.dateTime;          this.getFullDate(this.showDate);          this.emitChange();        }        break;      case 'multiple':        if (!day.isSelect && !day.isDisable) {          this.selectDate.push(day.dateTime);          this.getFullDate(this.showDate);          this.emitChange();        } else {          if (this.selectDate.length > 1) {            this.selectDate = this.selectDate.filter((item) => !item.isSame(day.dateTime));            this.getFullDate(this.showDate);            this.emitChange();          }        }        break;      case 'during':        if (day.isDisable) return;        if (this.restrictCurrentMonth && day.isGrey) return;        if (this.selectDate.length === 0) {          this.selectDate = [day.dateTime];        } else if (this.selectDate.length === 1) {          this.selectDate.push(day.dateTime);          if (this.selectDate[1].isBefore(this.selectDate[0])) {            this.selectDate.reverse();          }        } else if (this.selectDate.length === 2) {          this.selectDate = [day.dateTime];        }        this.getFullDate(this.showDate);        this.emitChange();        break;      }    },    // 切换年份    changeYear(action) {      const date = dayjs(`${this.showDate.year}-${this.showDate.month}`);      let computedDate;      switch (action) {      case 'prev':        this.translateX += 1;        computedDate = date.subtract(1, 'year');        break;      case 'next':        this.translateX -= 1;        computedDate = date.add(1, 'year');        break;      }      this.showDate = {        year: computedDate.year(),        month: computedDate.month() + 1,      };      this.emitSwitch(this.showDate);      this.getFullDate(this.showDate);    },    // 切换月份    changeMonth(action) {      const date = dayjs(`${this.showDate.year}-${this.showDate.month}`);      let computedDate;      switch (action) {      case 'prev':        this.translateX += 1;        computedDate = date.subtract(1, 'month');        break;      case 'next':        this.translateX -= 1;        computedDate = date.add(1, 'month');        break;      }      this.showDate = {        year: computedDate.year(),        month: computedDate.month() + 1,      };      this.emitSwitch(this.showDate);      this.getFullDate(this.showDate);    },    // 暴露出去的方法:切换已选的时间    changeDate(date) {      if (dayjs(date).isValid() || Array.isArray(date)) {        this.init(date);      } else {        console.error('Type of parameter is invalid!');      }    },    // 暴露出去的方法:切换当前显示的时间    changeDateView(date = dayjs()) {      const changeDate = dayjs(date);      this.showDate = {        year: changeDate.year(),        month: changeDate.month() + 1,      };      this.getFullDate(this.showDate);    },    getFullDate() {      const date = dayjs(`${this.showDate.year}-${this.showDate.month}`);      const thisDate = this.getDate(date);      const prevDate = this.getDate(date.subtract(1, 'month'));      const nextDate = this.getDate(date.add(1, 'month'));      this.fullDate = [        prevDate.fullDate,        thisDate.fullDate,        nextDate.fullDate,      ];    },    // 当前日期是否被选中    isSelect(date) {        // console.log(date)      let select = false;      switch (this.$props.mode) {      case 'single':        if (this.selectDate && date.isSame(this.selectDate)) {          select = true;        }        break;      case 'multiple':        if (this.selectDate.length > 0 && this.selectDate.some((item) => date.isSame(item))) {          select = true;        }        break;      }      return select;    },    // 当前时间是否在selectDate之间    isBetting(date) {      if (this.mode === 'during') {        const startDate = this.selectDate[0];        const endDate = this.selectDate[1];        if (this.selectDate.length === 1) {          return date.isSame(startDate);        } else if (this.selectDate.length === 2) {          return (date.isAfter(startDate) && date.isBefore(endDate)) || date.isSame(startDate) || date.isSame(endDate);        }      }      return false;    },    getIsDisable(dateTime) {      let isDisable = false;      const disabledDate = this.disabledDate.map((item) => dayjs(item).startOf('day'));      if (this.minDate || this.maxDate) {        if (this.minDate) {          const minDate = dayjs(this.minDate).startOf('day');          isDisable = dateTime.isBefore(minDate);        }        if (!isDisable && this.maxDate) {          const maxDate = dayjs(this.maxDate).endOf('day');          isDisable = dateTime.isAfter(maxDate);        }      } else if (disabledDate.length > 0) {        if (this.mode !== 'during') {          isDisable = disabledDate.some((item) => item.isSame(dateTime));        }      }      return isDisable;    },    getDate(thisDate) {      let date = [];      const prevDate = thisDate.subtract(1, 'month');      const nextDate = thisDate.add(1, 'month');      const firstDayOfWeek = thisDate.day() || 7;      const dayCountOfThisMonth = thisDate.daysInMonth();      const dayCountOfPrevMonth = prevDate.daysInMonth();      const prevIndexOfThisMonth = firstDayOfWeek - 1;      const NextIndexOfThisMonth = firstDayOfWeek + dayCountOfThisMonth - 2;      const disabledDate = this.disabledDate.map((item) => dayjs(item).startOf('day'));      for (let i = 0; i < 7 * 6; i++) {        // 上月        if (i < prevIndexOfThisMonth) {          const value = dayCountOfPrevMonth - (firstDayOfWeek - i - 2);          const dateTime = prevDate.date(value);          date[i] = {            value,            dateTime,            isGrey: true,            isToday: dateTime.isSame(dayjs().startOf('day')),            isSelect: this.isSelect(dateTime),            isDisable: this.getIsDisable(dateTime),            isDuring: this.isBetting(dateTime),          };        }        // 当月        if (          i >= prevIndexOfThisMonth &&          i <= NextIndexOfThisMonth        ) {          const value = i - firstDayOfWeek + 2;          const dateTime = thisDate.date(value);          date[i] = {            value,            dateTime,            isGrey: false,            isToday: dateTime.isSame(dayjs().startOf('day')),            isSelect: this.isSelect(dateTime),            isDisable: this.getIsDisable(dateTime),            isDuring: this.isBetting(dateTime),          };        }        // 下月        if (i > NextIndexOfThisMonth) {          const value = i - firstDayOfWeek - dayCountOfThisMonth + 2;          const dateTime = nextDate.date(value);          date[i] = {            value,            dateTime,            isGrey: true,            isToday: dateTime.isSame(dayjs().startOf('day')),            isSelect: this.isSelect(dateTime),            isDisable: this.getIsDisable(dateTime),            isDuring: this.isBetting(dateTime),          };        }      }      const fullDate = [];      for (let i = 0; i < 6; i++) {        fullDate.push(date.slice(i * 7, (i + 1) * 7));      }      return {        fullDate,      };    },  },};</script><style lang="less" scoped>@import './style.css';</style>

相关的style.css文件

.m-calendar {  background: #fff;  box-shadow: 0px 2px 6px 0px rgba(183, 183, 183, 0.2);}.m-calendar .m-toolbar {  padding-bottom: 0.36266667rem;}.m-calendar .m-toolbar {  display: flex;  height: 2.56rem;}.m-calendar .m-toolbar .m-month-selector,.m-calendar .m-toolbar .m-year-selector {  display: flex;  align-items: center;  justify-content: space-between;  padding-top: 0.74666667rem;}.m-calendar .m-toolbar .m-month-selector,.m-calendar .m-toolbar .m-year-selector {  line-height: 1.06666667rem;}.m-calendar .m-toolbar .m-month-selector,.m-calendar .m-toolbar .m-year-selector {  font-size: 0.768rem;  font-family: PingFangSC-Medium, PingFangSC;  font-weight: 500;  color: #29262a;}.m-calendar .m-toolbar .m-year-selector {  padding-left: 0.91733333rem;}.m-calendar .m-week-header {  padding: 0 0.91733333rem;}.m-calendar .m-week-header {  padding-bottom: 0.512rem;}.m-calendar .m-week-header {  position: relative;  display: flex;  box-sizing: border-box;  justify-content: space-between;  font-size: 0.59733333rem;}.m-calendar .m-week-header .m-week-day {  text-align: left;  line-height: 0.85333333rem;  font-family: PingFangSC-Regular, PingFangSC;  font-weight: 400;  color: #222222;}.m-calendar .m-months-container {  position: relative;  box-sizing: border-box;  height: 12.37333333rem;  overflow: hidden;}.m-calendar .m-months-container .m-months-wrapper {  position: absolute;  top: 0;  left: 0;  right: 0;  bottom: 0;}.m-calendar .m-months-container .m-months-wrapper .m-months {  position: absolute;  top: 0;  left: 0;  right: 0;  bottom: 0;  will-change: transform;  width: 16rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row {  padding-top: 0.512rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row {  width: 16rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row {  position: relative;  display: flex;  height: 1.408rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day {  margin-right: 0.87466667rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day:nth-child(1) {  margin-left: 0.66133333rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day {  font-size: 0.59733333rem;  font-family: PingFangSC-Medium, PingFangSC;  font-weight: 500;  color: #222222;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day {  position: relative;  height: 1.408rem;  width: 1.408rem;  line-height: 1.408rem;  text-align: center;  cursor: pointer;  -webkit-tap-highlight-color: transparent;  border-radius: 50%;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-day-num {  width: 1.408rem;  display: inline-block;  border-radius: 100%;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-day-num {  height: 1.408rem;  line-height: 1.408rem;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-grey {  color: #b8b8b8;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-today {  background: #5DABF3;  color: #fff;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-disable {  color: #b8b8b8;  text-decoration: line-through;}.m-calendar .m-months-container .m-months-wrapper .m-months .m-row .m-day .m-select {  background: #007aff;  color: #fff;}

3、使用到的页面

<div class="data">      <inlineCalendar :dayClick="dayClick" /></div>
<script>import inlineCalendar from '../components/inlineCalendar';export default {  name: "home",  data() {    return { };  },  components: {    inlineCalendar  },  methods: {    dayClick(date) {      console.log('date---->', date);      console.log(date.format('YYYY-MM-DD'));      let dates = date.format('YYYY-MM-DD');    },  }};</script><style lang="less" scoped>    .data {      position: fixed;      top: 1.87733333rem;      width: 100%;      height: 100%;    }</style>

以上就是“vue怎么实现左右滑动选择日期组件”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯