Cet article vous apporte des connaissances pertinentes sur les calendriers frontaux. Il explique principalement comment encapsuler un composant de calendrier personnalisé. Les amis intéressés peuvent y jeter un œil ci-dessous.
Comme nous le savons tous, de manière générale, s'il est nécessaire d'utiliser le composant calendrier dans un projet, il est souvent utilisé par des composants dans des bibliothèques d'interface utilisateur tierces ou par d'autres plug-ins tiers prêts à l'emploi. -ins. Pour de nombreux amis, lorsqu'ils voient pour la première fois le composant calendrier, ils pensent inconsciemment que c'est très compliqué et n'ont aucun moyen de commencer. Mais quand j’ai lu le code source de ce plug-in de calendrier, j’ai découvert que ce n’était pas aussi compliqué que je le pensais. Je pensais bêtement que si je voulais créer un composant de calendrier, je devrais obtenir des données de calendrier pour au moins dix ans avant et après l'année en cours avant de passer à l'étape suivante du développement.
Cependant, après avoir essayé de lire le code source de dycalendar.js, d'une part, j'ai senti que j'étais trop stupide et j'ai pensé au problème trop compliqué. J'admire également la clarté de pensée de l'auteur. Après l'avoir lu, je sens que j'en ai beaucoup bénéficié.
Après avoir débrouillé la logique de l'idée de l'auteur, j'ai développé un composant vue basé sur cette idée. Comme le montre l'image ci-dessous :
Ensuite, suivez-moi pour voir comment développer votre propre composant de calendrier.
année en cours
, mois en cours, <code>La date actuelle
, Le jour actuel de la semaine
, Le nombre de jours du mois en cours
, Le premier le jour du mois en cours correspond au jour de la semaine Combien de jours
, Combien de jours y avait-il au cours du mois dernier
, etc. 当前年
,当前月
,当前日期
,当前星期几
,当前月一共有几天
,当前月的第一天对应的是星期几
,上个月总共有多少天
等。
日历日期数据列表
,然后将其循环渲染到模板中。一般来说,成熟的日历组件,日期都是一个双向绑定的变量。为了方便使用,我们也采用双向绑定的方式。
<script setup> import { reactive, ref, computed, watch } from "vue"; const props = defineProps({ modelValue: Date, }); const emits = defineEmits(["update:modelValue"]); /** * 最小年份 */ const MIN_YEAR = 1900; /** * 最大年份 */ const MAX_YEAR = 9999; /** * 目标日期 */ const targetDate = ref(props.modelValue);
接下来,我们还需要初始化一些常量用来表示月份和日期:
/** * 有关月度的名称列表 */ const monthNameList = { chineseFullName: [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月", ], fullName: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ], mmm: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ], }; /** * 有关周几的名称列表 */ const dayNameList = [ { chineseFullName: "周日", chineseShortName: "日", fullName: "Sunday", shortName: "Sun", dayNumber: 0, }, { chineseFullName: "周一", chineseShortName: "一", fullName: "Monday", shortName: "Mon", dayNumber: 1, }, { chineseFullName: "周二", chineseShortName: "二", fullName: "Tuesday", shortName: "Tue", dayNumber: 2, }, { chineseFullName: "周三", chineseShortName: "三", fullName: "Wednesday", shortName: "Wed", dayNumber: 3, }, { chineseFullName: "周四", chineseShortName: "四", fullName: "Thursday", shortName: "Thu", dayNumber: 4, }, { chineseFullName: "周五", chineseShortName: "五", fullName: "Friday", shortName: "Fri", dayNumber: 5, }, { chineseFullName: "周六", chineseShortName: "六", fullName: "Saturday", shortName: "Sat", dayNumber: 6, }, ];
接下来,准备几个vue的响应式数据:
/** * 今日 */ const today = new Date(); /** * 日历的各项属性 */ const calendarProps = reactive({ target: { year: null, month: null, date: null, day: null, monthShortName: null, monthFullName: null, monthChineseFullName: null, firstDay: null, firstDayIndex: null, totalDays: null, }, previous: { totalDays: null, }, }); /** * 用于展现的日历数据 */ const calendarData = ref([]);
接下来,通过setCalendarProps
方法获取日历的各个属性,逐个填充calendarProps
中的数据:
function setCalendarProps() { if (!targetDate.value) { targetDate.value = today; } // 获取目标日期的年月日星期几数据 calendarProps.target.year = targetDate.value.getFullYear(); calendarProps.target.month = targetDate.value.getMonth(); calendarProps.target.date = targetDate.value.getDate(); calendarProps.target.day = targetDate.value.getDay(); if ( calendarProps.target.year < MIN_YEAR || calendarProps.target.year > MAX_YEAR ) { console.error("无效的年份,请检查传入的数据是否是正常"); return; } // 获取到目标日期的月份【中文】名称 let dateString; dateString = targetDate.value.toString().split(" "); calendarProps.target.monthShortName = dateString[1]; calendarProps.target.monthFullName = monthNameList.fullName[calendarProps.target.month]; calendarProps.target.monthChineseFullName = monthNameList.chineseFullName[calendarProps.target.month]; // 获取目标月份的第一天是星期几,和在星期几中的索引值 const targetMonthFirstDay = new Date( calendarProps.target.year, calendarProps.target.month, 1 ); calendarProps.target.firstDay = targetMonthFirstDay.getDay(); calendarProps.target.firstDayIndex = dayNameList.findIndex( (day) => day.dayNumber === calendarProps.target.firstDay ); // 获取目标月份总共多少天 const targetMonthLastDay = new Date( calendarProps.target.year, calendarProps.target.month + 1, 0 ); calendarProps.target.totalDays = targetMonthLastDay.getDate(); // 获取目标月份的上个月总共多少天 const previousMonth = new Date( calendarProps.target.year, calendarProps.target.month, 0 ); calendarProps.previous.totalDays = previousMonth.getDate(); }
需要注意的一个知识点是,在获取本月多少天和上个月多少天的时候,都将date值设置为了
0
。这是因为当date值为0
的时候,返回的Date对象是上个月的最后一天。所以说,为了获取本月多少天,需要将本月的month值加1
。
执行这个方法之后,此时calendarProps
的值为:
当我们已经知道本月第一天对应的周几索引值、本月一共有多少天和上个月一共有多少天这三个核心数据之后,就可以开始生成对应的日历数据了。
思路如下:
1
。然后从本月第一天对应的周几索引值开始进行递增。本月之前的日期和之后的日期设置一个算法进行计算。dateType
,表示是本月还是上月还是下月;/** * 生成日历的数据 */ function setCalendarData() { let i; let date = 1; const originData = []; const firstRow = []; // 设置第一行数据 for (i = 0; i <= 6; i++) { // 设置目标月份之前月份的日期数据 if (i < calendarProps.target.firstDayIndex) { const previousDate = calendarProps.previous.totalDays - calendarProps.target.firstDayIndex + (i + 1); firstRow.push({ dateObj: new Date( calendarProps.target.year, calendarProps.target.month - 1, previousDate ), dateNumber: previousDate, dateType: "previous" }); } else { // 设置目标月份当月的日期数据 firstRow.push({ dateObj: new Date( calendarProps.target.year, calendarProps.target.month, date ), dateNumber: date, dateType: "current" }); date++; } } originData.push(firstRow); // 设置后面五行的数据 for (let j = 0; j <= 4; j++) { const rowData = []; for (let k = 0; k <= 6; k++) { // 设置目标月份剩下的日期数据 if (date <= calendarProps.target.totalDays) { rowData.push({ dateObj: new Date( calendarProps.target.year, calendarProps.target.month, date ), dateNumber: date, dateType: "current" }); } else { // 设置目标月份下个月的日期数据 const nextDate = date - calendarProps.target.totalDays; rowData.push({ dateObj: new Date( calendarProps.target.year, calendarProps.target.month + 1, nextDate ), dateNumber: nextDate, dateType: "next" }); } date++; } originData.push(rowData); } calendarData.value = originData; }
至此,这个日历组件的核心部分的逻辑就已经实现了。你看,是不是很简单?
接下来,我们只需要根据calendarData
liste de données de date de calendrier
spécifique, puis restituez-la dans le modèle en boucle. 🎜🎜Lorsque vous changez de mois, obtenez les données clés correspondant à la nouvelle date cible. Une fois que vue a détecté des modifications dans les attributs du calendrier, elle demande à la page de la mettre à jour. 🎜setCalendarProps
, et remplissez les données dans calendarProps
une par une : 🎜rrreee🎜 Points à noter Un point de connaissance est que lors de l'obtention du nombre de jours de ce mois et du nombre de jours du mois dernier, la valeur de date est définie sur🎜Après avoir exécuté cette méthode, la valeur de0
. En effet, lorsque la valeur de date est0
, l'objet Date renvoyé est le dernier jour du mois précédent. Par conséquent, afin d'obtenir le nombre de jours de ce mois, vous devez ajouter1
à la valeur mensuelle de ce mois. 🎜
calendarProps
est : 🎜🎜🎜1
. Commencez ensuite à incrémenter à partir de la valeur de l'indice du jour de la semaine correspondant au premier jour du mois. Définissez un algorithme pour calculer les dates avant et après ce mois. 🎜🎜Afin de faciliter le changement de date et la différenciation de style ultérieurement, les données générées sont traitées dans un objet, qui contient le type de date - dateType
, indiquant s'il s'agit de ce mois, du mois précédent ou du suivant. mois ; 🎜 ol>rrreee🎜À ce stade, la logique de base de ce composant de calendrier a été implémentée. Écoutez, n'est-ce pas très simple ? 🎜🎜Ensuite, il nous suffit de restituer le modèle html correspondant et d'ajouter des styles basés sur les données de calendarData
. 🎜 De manière générale, les composants du calendrier ont une structure de type grille, j'ai donc choisi la méthode du tableau pour le rendu. Mais si vous me demandez s'il existe d'autres moyens, il en existe encore, comme l'utilisation d'une disposition flexible ou d'une disposition en grille, mais si cette méthode est utilisée, la structure des données de calendarData
ne sera pas ce qu'elle est actuellement.
La structure du dom est la suivante :
En ce qui concerne l'effet fluide de la bordure du bouton, je l'ai réalisé en référence à l'article de Su Su. Pour plus de détails, veuillez consulter :
Clip-path réalise le flux du bouton. animation de bordurejuejin.cn/post /719877…
Ensuite, la partie de style restante peut être improvisée ou dessinée selon le dessin de conception de l'interface utilisateur. Je crois que vous avez tous expérimenté les dessins de conception exquis des sœurs de l'interface utilisateur (hee hee
La partie spécifique du code ne sera pas publiée dans l'article. Si nécessaire, vous pouvez directement consulter le code source complet ci-dessous
Pour certains composants qui semblent gênants, la logique de base n'est peut-être pas si compliquée. Parfois, vous aurez peut-être juste besoin d'un peu de patience pour lire le code ligne par ligne et clarifier les idées
Recommandé. apprentissage : "tutoriel vidéo vue"
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!