"Vue3+Typescript" a simple calendar component implementation

This is a front-end blogger without routines. He is keen on all kinds of front-end oriented operations. He often writes wherever he thinks. If you are interested in technology and front-end effects, you can leave a message~ The blogger will step on the pit for everyone after seeing it. the ~

Homepage: Oliver Yin's homepage

Motto: Get up when you fall~

Table of contents

I. Introduction

2. Rendering

3. Core ideas

4. Code implementation

4.1 Calculation of the date of this month

4.2 Complete the date of the previous month

4.3 Completing the next month's date

4.4 Convert to binary array

4.5 Using v-for to generate a calendar

4.6 Lunar calendar, holidays, etc.

V. Summary


I. Introduction

Recently, a calendar component needs to be used in the project. Since I searched and couldn’t find a suitable one, I decided to make one by myself. The project must be more complicated than this. Here is just an idea or development direction for each small partner. ~

After reading it patiently, you may gain something... (PS: If you want to leave the source code with an email address, the blogger will send it after seeing it~)

2. Rendering

The general effect diagram is as follows:

3. Core ideas

Personally, the core of the calendar is to  calculate the day of the week on the first day of the specified month . Why? Because, in terms of form, the calendar is displayed as such a 7*6 rectangle . If you know the day of the week on the 1st, you can fill in the date before the 1st, and you can also fill in the date after the last day. ;

Therefore, the calculation of the calendar can be divided into three sections:

  • The first paragraph, the calculation of this month, calculates the current day of the week on the 1st, and then calculates the total number of days in this month;
  • The second paragraph, calculated last month, counts the total number of days before the 1st;
  • The third paragraph, next month calculation, calculates the total number of days after this month;

In this way, the three segments are connected together to form a complete set of current arrays . If it is not clear, let’s give another example. Take July 2023 as an example. The 1st of July is Saturday, so it should be in the rectangle this position of

Then there should be 6 days before Saturday, and the last 6 days of June need to be used to complete the first half of the rectangle ;

Then calculate the last day of July, July 31 is Monday, then it should be in this position

Such a complete rectangle (calendar) is complete from the perspective of data;

4. Code implementation

4.1 Calculation of the date of this month

The calculation of the date of this month is divided into two parts, the first part is to get the current date , and the second part is to get the week of the 1st of this month

First get the current date

// 获取当前日期
function getCurrent() {
    const date = new Date();
    return [date.getFullYear(), date.getMonth() + 1, date.getDate()];
}

First get this month, very simple

/**
 * 获取公历某一天是星期几
 * @param {number} y 年
 * @param {number} m 月
 * @param {number} d 日
 * @returns {number} 返回星期数字[0-6]
 */
function solarWeek(y: number, m: number, d: number) {
  let date = new Date(y, m - 1, d);
  let week = date.getDay();
  return week;
}

const currentDate = getCurrent()
// 使用
this.solarWeek(currentDate[0], currentDate[1], 1)

In this way, we get the day of the first day;

4.2 Complete the date of the previous month

One thing to note about the data acquisition of the previous month is that if the current month is January, then the December of the previous year to be obtained, therefore, the current month must be determined first before calculation

// 判断年度
const y = date[1] === 1 ? date[0] - 1 : date[0];
// 判断月份
const m = date[1] === 1 ? 12 : date[1] - 1;

The next step is to judge the number of dates that need to be completed. It is very simple. We only need to judge according to the day of the week. If it is Saturday, then it is 6 days (Monday to Friday, plus Sunday), if it is Friday , then it is to make up 5 days (Monday to Thursday, plus Sunday);

 /**
   * 获取当月前面需补齐的数组
   */
beforDays(date: number[], last: number) {
    const y = date[1] === 1 ? date[0] - 1 : date[0];
    const m = date[1] === 1 ? 12 : date[1] - 1;

    const arr: dateBase[] = [];
    for (let i = 0; i < last; i++) {
        arr.push({...});
    }
    return arr;
}

This last is the week of the 1st, which is the number of cycles that need to be repeated;

4.3 Completing the next month's date

Then make up the next month, which is the same as the calculation of the previous month. First, it is necessary to judge whether it is December. If it is December, then the next month is January of the next year.

const y = date[1] === 12 ? date[0] + 1 : date[0];
const m = date[1] === 12 ? 1 : date[1] + 1;

Then, since we know the number of days in the current month and the number of days completed in the previous month, we can naturally calculate how many days need to be completed in the next month, 42-the number of days in the current month-the number of days in the previous month =the number of days in the next month number of days ;

/**
 * 获取当月后面需补齐的数组
 */
afterDays(day: dateBase[], date: number[]) {
    const arr: dateBase[] = [];
    const y = date[1] === 12 ? date[0] + 1 : date[0];
    const m = date[1] === 12 ? 1 : date[1] + 1;

    for (let i = 1; i < 42 - day.length + 1; i++) {
        arr.push({...});
    }
    return [...day, ...arr];
}

At this point, we can get an array with a length of 42 , which represents a total of 42 days from the last day of last month to this month and then to the positive day of next month;

4.4 Convert to binary array

The reason for converting it into a two-digit array is very simple, because our calendar is a two-digit array in terms of layout. There are 6 rows in total, and each row has 7 grids, right, so we need to convert it, The code to turn is also very simple

const dateArray = [];
for (let row = 0; row < 6; row++) {
    dateArray.push(allDate.splice(0, 7));
}

4.5 Using v-for to generate a calendar

After the basic data sorting is completed, you only need to generate grids in batches through Vue's v-for command;

<template v-if="TBody.length">
  <div
    class="t-calendar-row"
    v-for="(item, index) in TBody"
    :key="index"
    >
    <div
      class="t-calendar-col"
      v-for="(col, colIdx) in item"
      :key="colIdx"
      >
      <CalendarItem
        :col="col"
        :time="selectedTime"
        @changeTargetDate="changeDate"
        ></CalendarItem>
    </div>
  </div>
</template>
<template v-else>
  <div class="no-date">抱歉,暂无数据</div>
</template>

As for the style of each grid, it can be customized according to the needs;

4.6 Lunar calendar, holidays, etc.

The real calendar must be far more than these basic data, and must also include: lunar calendar, festivals, holidays, etc. different markings, these can be calculated together with the value corresponding to the current date, and rendered through v-for It is enough to render the corresponding CSS style at any time, for example, when performing data push:

arr.push({
  // 日期
  title: w - i,
  // 是否本月
  isCurrent: false,
  // 是否节假日
  isHolidays: DateClass.getHolidays([y, m, w - i]),
  date: `${y}-${clockFactory(m)}-${clockFactory(w - i)}`,
  // 阴历
  lunars: lun,
  isNow: false,
  // 阳历节日,如国庆,元旦
  solarDay: DateClass.getSolarDay(m, w - i),
  // 农历节日,如中秋,春节,端午
  lunarDay: DateClass.getlunarDay(Number(l[0]), Number(l[1]), Number(l[2])),
  // 生肖
  animal: DateClass.getAnimal(Number(l[0])),
  // 星座
  astro: DateClass.toAstro(y, m, w - i),
  // 节气
  term: getTerm(Number(l[0]), m, w - i)
});

And so on can be processed together when the data is processed;

V. Summary

In fact, after knowing the generation principle of the calendar, I actually feel that the calendar is not so difficult to implement, but it is a little troublesome, and the final realization needs to be determined according to actual needs;

Guess you like

Origin blog.csdn.net/zy21131437/article/details/131995484