Это front-end блоггер без рутины.Он увлекается всеми видами front-end ориентированных операций.Он часто пишет то,что думает.Если вас интересуют технологии и front-end эффекты,то можете оставить сообщение~ Блогер наступит на яму для всех, увидев это.
Домашняя страница: Домашняя страница Оливера Иня
Девиз: Вставай, когда падаешь~
Оглавление
4.2 Завершите дату предыдущего месяца
4.3 Завершение даты следующего месяца
4.4 Преобразование в двоичный массив
4.5 Использование v-for для создания календаря
4.6 Лунный календарь, праздники и т.д.
Введение
Недавно в проекте нужно было использовать компонент календаря.Поскольку я искал и не нашел подходящего, то решил сделать его сам.Проект должен быть сложнее этого.Вот только идея или направление развития за каждого маленького партнера. ~
После терпеливого прочтения вы можете что-то обрести... (PS: Если вы хотите оставить исходный код с адресом электронной почты, блоггер пришлет его после просмотра~)
2. Рендеринг
Общая схема эффекта выглядит следующим образом:
3. Основные идеи
Лично ядром календаря является вычисление дня недели в первый день указанного месяца Почему? Потому что, с точки зрения формы, календарь отображается как такой прямоугольник 7 * 6. Если вы знаете день недели 1-го числа, вы можете заполнить дату до 1-го числа, а также можете заполнить дату после последний день.;
Поэтому расчет календаря можно разделить на три раздела:
- Первый пункт, расчет этого месяца, вычисляет текущий день недели 1 числа, а затем вычисляет общее количество дней в этом месяце;
- Второй пункт, рассчитанный в прошлом месяце, подсчитывает общее количество дней до 1 числа;
- Третий абзац, расчет следующего месяца, вычисляет общее количество дней после этого месяца;
Таким образом, три сегмента соединяются вместе, чтобы сформировать полный набор текущих массивов.Если непонятно, давайте приведем другой пример.В качестве примера возьмем июль 2023.1 июля - суббота, поэтому он должен быть в прямоугольник это положение
Затем должно быть 6 дней до субботы, а последние 6 дней июня нужно использовать для завершения первой половины прямоугольника ;
Затем вычислить последний день июля, 31 июля понедельник, тогда он должен быть в этом положении
Такой полный прямоугольник (календарь) является полным с точки зрения данных;
4. Реализация кода
4.1 Расчет числа этого месяца
Расчет даты этого месяца делится на две части: первая часть - получение текущей даты , а вторая часть - получение недели 1-го числа этого месяца.
Сначала получите текущую дату
// 获取当前日期
function getCurrent() {
const date = new Date();
return [date.getFullYear(), date.getMonth() + 1, date.getDate()];
}
Сначала получите в этом месяце, очень просто
/**
* 获取公历某一天是星期几
* @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)
Таким образом, мы получаем день первого дня;
4.2 Завершите дату предыдущего месяца
Одна вещь, которую следует отметить в отношении сбора данных за предыдущий месяц, заключается в том, что если текущим месяцем является январь, то необходимо получить декабрь предыдущего года, поэтому текущий месяц необходимо определить перед расчетом.
// 判断年度
const y = date[1] === 1 ? date[0] - 1 : date[0];
// 判断月份
const m = date[1] === 1 ? 12 : date[1] - 1;
Следующим шагом является оценка количества дат, которые необходимо выполнить. Это очень просто. Нам нужно только судить по дню недели. Если это суббота, то это 6 дней (с понедельника по пятницу, плюс Воскресенье), если это пятница, то это составляет 5 дней (с понедельника по четверг плюс воскресенье);
/**
* 获取当月前面需补齐的数组
*/
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;
}
Это последняя неделя 1-го, это количество циклов, которые необходимо повторить;
4.3 Завершение даты следующего месяца
Затем составить следующий месяц, который аналогичен расчету предыдущего месяца.Во-первых, необходимо судить, является ли это декабрь.Если это декабрь, то следующий месяц является январем следующего года.
const y = date[1] === 12 ? date[0] + 1 : date[0];
const m = date[1] === 12 ? 1 : date[1] + 1;
Затем, так как мы знаем количество дней в текущем месяце и количество дней, пройденных в предыдущем месяце, мы можем естественным образом подсчитать, сколько дней нужно выполнить в следующем месяце, 42-количество дней в текущем месяце -количество дней в предыдущем месяце = количество дней в следующем месяце количество дней ;
/**
* 获取当月后面需补齐的数组
*/
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];
}
На данный момент мы можем получить массив длиной 42 , который представляет в общей сложности 42 дня с последнего дня прошлого месяца до этого месяца, а затем до положительного дня следующего месяца;
4.4 Преобразование в двоичный массив
Причина преобразования его в двузначный массив очень проста, потому что наш календарь представляет собой двузначный массив с точки зрения макета.Всего 6 строк, и каждая строка имеет 7 сеток, верно, поэтому нам нужно преобразовать это, Код для поворота тоже очень простой
const dateArray = [];
for (let row = 0; row < 6; row++) {
dateArray.push(allDate.splice(0, 7));
}
4.5 Использование v-for для создания календаря
После того, как базовая сортировка данных завершена, вам нужно только генерировать сетки партиями с помощью команды Vue v-for;
<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>
Что касается стиля каждой сетки, его можно настроить в соответствии с потребностями;
4.6 Лунный календарь, праздники и т.д.
Реальный календарь должен быть намного больше, чем эти основные данные, а также должен включать в себя: лунный календарь, фестивали, праздники и т. д. различные отметки, которые можно рассчитать вместе со значением, соответствующим текущей дате, и отобразить через v-for It. достаточно для рендеринга соответствующего стиля CSS в любое время, например, при выполнении 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)
});
И так далее можно обрабатывать вместе при обработке данных;
V. Резюме
Фактически, после того, как я узнал принцип генерации календаря, я действительно чувствую, что календарь не так уж и сложен в реализации, но это немного хлопотно, и окончательная реализация должна определяться в соответствии с фактическими потребностями;