您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么封裝一個vue自定義日歷組件”,在日常操作中,相信很多人在怎么封裝一個vue自定義日歷組件問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么封裝一個vue自定義日歷組件”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
獲取到目標日期數據
獲取到當前日期的各項重要屬性,諸如當前年
,當前月
,當前日期
,當前星期幾
,當前月一共有幾天
,當前月的第一天對應的是星期幾
,上個月總共有多少天
等。
根據這些屬性,來生成具體的日歷日期數據列表
,然后將其循環渲染到模板中。
當切換月份的時候,獲取到新的目標日期對應的各項關鍵數據。vue檢測到日歷屬性變化之后,通知頁面進行更新。
一般來說,成熟的日歷組件,日期都是一個雙向綁定的變量。為了方便使用,我們也采用雙向綁定的方式。
<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
的值為:
當我們已經知道本月第一天對應的周幾索引值、本月一共有多少天和上個月一共有多少天這三個核心數據之后,就可以開始生成對應的日歷數據了。
思路如下:
由于大部分情況下,本月的第一天不是從頭開始的,之前的部分是上個月的日期。所以第一行要單獨進行處理。
設置一個公用的date數值,初始值設置為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
中的數據渲染出相應的html模板和添加上樣式就可以了。
一般來說,日歷組件都是網格狀的結構,所以我選擇table的方式進行渲染。不過你要是問我還有沒有別的方式,那還是有的,比如使用flex布局或者grid布局,但是如果采用這種方式的話,calendarData
的數據結構就不是現在這個樣子了。
dom結構如下圖:
到此,關于“怎么封裝一個vue自定義日歷組件”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。