Напишите компонент календаря с помощью vue (очень подробно — сделайте календарь простым)

Vue.js

Я считаю, что у многих друзей, таких как я, возникает головная боль, когда они упоминают календарь, а затем отправляются в Интернет в поисках простых в использовании компонентов календаря, таких как element-ui, но календарь разработан другими и разработан с их помощью. собственный пользовательский интерфейс.В конце концов, функциональный стиль не может быть на 100% похожим, поэтому в настоящее время вы можете либо пойти на git, чтобы найти похожий, а затем изменить код, либо вы можете разработать только один самостоятельно, поэтому я также делюсь идеи упаковки компонентов календаря, которые я изучил сам. ;

Хотя я знаю, что компонент календаря, должно быть, был опубликован многими людьми и написаны идеи, но я все еще хочу написать об этом.

Готов к работе

Я решил получить новый скаффолд для разработки, поэтому я зашел на официальный сайт vue-cli, чтобы получить новый скаффолд локально, я считаю, что все должны это знать. После успешного извлечения запускается npm serve;

Затем я привык писать стили CSS меньшими средствами, поэтому я устанавливаю все меньше и меньше загрузчика, и это зависит от человека к человеку;

Начинать

Я считаю, что многие мелкие партнеры не знают, как начать работу после того, как я увижу календарь, как я, как я могу отличить вверх и вниз и текущий месяц, очень просто понять идеи и принципы.

Календарь имеет дни 42 и дни 35. Причина в том, что есть строки 6 или 7, а строки 7 более полны. Преимущество 42 дней в том, что он может отображать предыдущий месяц, текущий месяц и следующий месяц. недостатком является предыдущий месяц.по сравнению со следующим месяцем на него приходится больше,и он несколько избыточен.если будет 35 дней,то будет выглядеть более упорядоченно,но некоторые месяцы нельзя полностью отобразить и все равно нужно 42 дня.это не вредно.В качестве примера возьмем 42 дня;

Прежде всего, нам нужно посмотреть, какой день является первым днем ​​текущего месяца, а 1-е число мая - это среда, затем использовать 42 - 2 (здесь обратите внимание, что если это воскресенье в первый день, это 42 - день недели, если это понедельник первого дня недели) Один 42 - (день недели - 1) а остальное число текущего месяца и следующего месяца.

我创建一个公共js里面放一些公共的方法方便在组件中调用;公共的js我就叫utils.js;
getYearMonthDay 就是utils里面的一个公共方法,是为了方便获取年月日;
const getYearMonthDay =  (date) => {
 let year = date.getFullYear();
 let month = date.getMonth();
 let day = date.getDate();
 return {year, month, day};
};

computed: {
    visibleCalendar: function () {
        let calendatArr = [];
        先得到当前的年,月,日
        let {year, month, day} = utils.getNewDate(utils.getDate(this.time.year, this.time.month, 1));
        
        获取当月的第一天 得到2019-5-1
        let currentFirstDay = utils.getDate(year, month, 1);
        
        获取第一天是星期几 得到 3
        let weekDay = currentFirstDay.getDay();
        
        用当月的第一天减去 周几前面几天 这样就能得到上个月开始的天数 (当前月1号是周三,那么周一就是上个月的最后两天)
        let startTime = currentFirstDay - (weekDay - 1) * 24 * 60 * 60 * 1000;
        
        然后得到所有的日期
        for (let i = 0; i < 42; i++) {
          calendatArr.push({
            date: new Date(startTime + i * 24 * 60 * 60 * 1000),
            year: year,
            month: month + 1,
            day: new Date(startTime + i * 24 * 60 * 60 * 1000).getDate()
          })
        };
        return calendatArr
    }
}

Затем структура dom переходит в v-для этого массива, так что вы можете получить начальный календарь

Но это некрасиво, и невозможно отличить, какой день является предыдущим месяцем, а какой днем ​​​​следующим месяцем, поэтому нам нужно добавить стиль к следующему месяцу, чтобы отличать текущий месяц от следующего месяца

<ul class="calendar-view clear">
  <li v-for="(item, index) in visibleCalendar" 
    :key="index" 
    class="date-view"
    :class="[
      {'notCurrentMonth-class': !isCurrentMonth(item.date)},
      {currentDay: isCurrentDay(item.date)},
    ]"
    @click="handleClickDay(item, index)"
  >
    <span class="date-day" >
      {{item.day}}
    </span>
  </li>
</ul>
notCurrentMonth-class 是区分上下月的类名
currentDay 是判断是否是今天的类名

判断是否是当前月的方法,传入每一天 用传入的每一天去和当前年月做比较然后返回
isCurrentMonth (date) {
    let {year: currentYear, month: currentMonth} = utils.getYearMonthDay(utils.getDate(this.time.year, this.time.month, 1));
    let {year, month} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month
}
判断是否是当前天的方法 同理
isCurrentDay (date) {
    let {year: currentYear, month: currentMonth, day: currentDay} = utils.getYearMonthDay(new Date());
    let {year, month, day} = utils.getYearMonthDay(date);
    return currentYear == year && currentMonth == month && currentDay == day;
}

Затем добавьте несколько стилей, которые вам нравятся, к имени класса, вы можете с радостью различать текущий месяц, следующий месяц и сегодняшний день.

Теперь нужно просто переключаться влево и вправо и щелкнуть сегодня, чтобы вернуться к текущему месяцу.Следующий шаг очень прост.Давайте сначала напишем два метода для переключения верхнего и нижнего месяцев.

先去utils里面创建一个新的方法用来获取当前几月几日
const getDate = (year, month, day) => {
  return new Date(year, month, day);
}
在data () {
    let {year, month, day} = utils.getYearMonthDay(new Date());
    return {
        yearMonth: {year, month, day}, 
    }
}
// 上一个月 获取当年月 用setMonth()去设置月份,然后更新yearMonth
  handlePrevMonth () {
    let prevMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1);
    prevMonth.setMonth(prevMonth.getMonth() - 1);
    this.yearMonth = utils.getYearMonthDay(prevMonth);
  }
  // 下一个月 获取当年月 用setMonth()去设置月份,然后更新yearMonth
  handleNextMonth () {
    let nextMonth = utils.getDate(this.yearMonth.year,this.yearMonth.month,1); 
    nextMonth.setMonth(nextMonth.getMonth() + 1);
    this.yearMonth = utils.getYearMonthDay(nextMonth);
  }
  // 点击回到今天 同理
  handleToday () {
    this.yearMonth = utils.getYearMonthDay(new Date());
  }

Просто переключитесь влево и вправо и нажмите, чтобы вернуться к сегодняшнему календарю.Разве это не очень просто?

адрес календаря gitHub приветствую всех

Залил подробный код на свой гитхаб, более подробно написал на git, а также предусмотрел некоторые внешние кликовые события, чтобы некоторые методы внутри можно было вызывать вне компонента, что удобнее в использовании. неплохо, можно зайти на гит дать звезду или что-то в этом роде.Спасибо за поддержку.Если что-то не так, пожалуйста, укажите на это и обсудите это вместе!