不知道得多久没有写过文章了,从今年开始心情就一直很浮躁,静不下来…
这次写这个东西其实也很简单,主要是帮其他项目的同事写的,有些东西其实还可以继续封装的,但是我太懒了,就交给jym了。
先上图看看效果吧
主要依赖
amfe-flexible
postcss-pxtorem
dayjs
vant
这里主要说一下 amfe-flexible
和 postcss-pxtorem
,这个就是用来做移动端的适配,就像一般UI给的设计稿都是750px的,但是我们在实际开发的时候可能是不同的,所以用这个来做适配,下面是配置文件
postcss.config.js
const autoprefixer = require('autoprefixer');
const px2rem = require('postcss-pxtorem');
module.exports = {plugins: [autoprefixer(), px2rem({rootValue: 75, unitPrecision: 5, propList: ['*'], selectorBlackList: [//这里样式需要排除vant组件的,因为vant本身就是移动端的样式了'van-']})],
};
主要逻辑
工具类
这些工具类就是普通的获取月数什么的,没有什么好讲的
calendar.js
// 判断是否周末
export const isWeekend = (date) => {return [0, 6].includes(new Date(date).getDay())
}
// 获取年份
export const getDateYear = (date) => {return new Date(date).getFullYear()
}
// 获取月份
export const getDateMonth = (date) => {return new Date(date).getMonth() + 1
}
// 获取月份天数
export const getMonthDay = (date) => {let year = new Date(date).getFullYear()let month = new Date(date).getMonth() + 1return new Date(year, month, 0).getDate()
}
// 获取月份第一天是周几
export const getMonthFirstDayOrder = (date) => {let year = new Date(date).getFullYear()let month = new Date(date).getMonth()return new Date(year, month, 1).getDay()
}
// 获取上个月有多少天
export const getPrevMonthDay = (date) => {let year = new Date(date).getFullYear()let month = new Date(date).getMonth()if (month === 0) {year--month = 12}return new Date(year, month, 0).getDate()
}
月份处理
这里我是采用二维数组的方式来处理每周的数据,而且我们处理月份的时候需要考虑下面几点
- 普通月份处理(这不是说废话吗),即每个月的第一天是星期几,排在第几位
- 上个月/下个月处理,上个月是几月份,多少天,是否在同一年(下个月同理)
- 周末(这里就不考虑节假日什么的了)
- 要显示多少周,最多可能有6周(1号在周六,因为我这里是以周日为第一位,然后有31天的情况)
下面就是主要的逻辑处理代码了
calendar.vue
// 初始化日历数据initMonthData(date) {this.dateArr = [[], [], [], [], [], []]// 每个月第一天排在第几位let firstDayOrder = getMonthFirstDayOrder(date)// 选择器选择的年份let selectedYear = getDateYear(date)// 选择器选择的月份let selectedMonth = getDateMonth(date)// 选择器选择的月份天数let selectedMonthDay = getMonthDay(date)// 选择器选择的月份的上个月的总天数let prevMonthDay = getPrevMonthDay(date)// 月份渲染记数let selectedCountDay = 0// 下个月月份渲染记数let nextMonthCountDay = 0// 是否下个月let isNextMonth = falsefor (let weekIndex = 0; weekIndex < 6; weekIndex++) {for (let dayIndex = 0; dayIndex < 7; dayIndex++) {if (weekIndex === 0) {// 第一周需要对某一个月第一天做定位if (firstDayOrder <= dayIndex) {// 当前月selectedCountDay += 1this.$set(this.dateArr[weekIndex], dayIndex, {date: new Date(selectedYear,selectedMonth - 1,selectedCountDay),status: {isCurr: true, // 是否当月isPrev: false, // 是否上个月isNext: false, // 是否下个月// 是否周末isWeekend: isWeekend(new Date(selectedYear, selectedMonth - 1, selectedCountDay))}})} else {// 上个月 因为选择月份是当前月 上个月需要减去1 然后new Date()还需要再减去1let prevMonth = selectedMonth === 1 ? 11 : selectedMonth - 2let prevMonthYear =selectedMonth - 1 === 0 ? selectedYear - 1 : selectedYearthis.$set(this.dateArr[weekIndex], dayIndex, {date: new Date(prevMonthYear,prevMonth,prevMonthDay - firstDayOrder + dayIndex + 1),status: {isCurr: false,isPrev: true,isNext: false,isWeekend: isWeekend(new Date(prevMonthYear,prevMonth,prevMonthDay - firstDayOrder + dayIndex + 1))}})}} else {selectedCountDay += 1isNextMonth = selectedCountDay > selectedMonthDayif (!isNextMonth) {// 当前月this.$set(this.dateArr[weekIndex], dayIndex, {date: new Date(selectedYear,selectedMonth - 1,selectedCountDay),status: {isCurr: true,isPrev: false,isNext: false,isWeekend: isWeekend(new Date(selectedYear, selectedMonth - 1, selectedCountDay))}})} else {// 下个月let nextMonth = selectedMonth === 12 ? 0 : selectedMonthlet nextYear =selectedMonth === 12 ? selectedYear + 1 : selectedYearnextMonthCountDay += 1this.$set(this.dateArr[weekIndex], dayIndex, {date: new Date(nextYear, nextMonth, nextMonthCountDay),status: {isCurr: false,isPrev: false,isNext: true,isWeekend: isWeekend(new Date(nextYear, nextMonth, nextMonthCountDay))}})}}}}while (getDateMonth(this.dateArr[this.dateArr.length - 1][0].date) !==selectedMonth) {// 某些月份不用六个星期 去除不需要的数据this.dateArr.pop()}},
部分样式处理
就是根据item里面的状态进行动态class处理
handleDayClass(item, dayIndex, weekIndex) {let classStr = `${item.status.isWeekend || item.status.isNext || item.status.isPrev? ' day_prev_next_weekend': ''}${dayjs(item.date).isSame(dayjs(this.currDate), 'day') ? ' day_curr' : ''}${dayIndex === this.clickDayIndex && weekIndex === this.clickWeekIndex? ' day_active': ''}`return classStr}
然后那个弹窗就是用vant组件的van-popover
,然后再初始化的时候给每一个item设置一个值与对应组件绑定,记得用$set
,不然数据可能是视图不对应。
最后
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享