直接先把我的代码贴上
* {
margin: 0;
padding: 0;
list-style: none;
font-size: 16px;
}
#calendar {
width: 50%;
margin: 120px auto;
padding: 10px;
/* background: #ccc; */
border-radius: 5px;
overflow: hidden;
background: #28a1ff;
}
.month {
background: #28a1ff;
color: #fff;
height: 32px;
margin: 0 auto;
padding: 0 10px;
}
.month ul {
margin: 0 auto;
height: 32px;
width: 90%;
display: flex;
align-items: center;
justify-content: space-between;
}
.month ul li {
cursor: pointer;
}
.arrow {
width: 32px;
text-align: center;
}
.weekdays,
.days {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
align-items: center;
justify-items: center;
padding: 10px 10px;
}
.weekdays {
grid-template-rows: 32px;
background: #28a1ff;
color: #fff;
}
.days {
grid-template-rows: 32px 32px 32px 32px 32px;
background-color: #0986e7;
color: #fff;
padding-top: 10px;
border-radius: 5px;
}
.days li {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-items: center;
}
.days li span {
width: 100%;
height: 100%;
text-align: center;
line-height: 32px;
}
.other-month {
color: #ccc;
}
.active {
background: #28a1ff;
border-radius: 5px;
}
.this-month:hover {
cursor: pointer;
background: #28a1ff;
border-radius: 5px;
}
.year-container,
.month-container {
background: #fff;
padding: 10px;
border-radius: 5px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 5px;
width: 240px;
position: fixed;
}
.year-container span,
.month-container span {
text-align: center;
cursor: pointer;
}
.year-container span:hover,
.month-container span:hover {
color: #28a1ff;
}
.isYear,
.isMonth {
color: #28a1ff;
}
<div id="calendar" ref="calendar">
<!-- 年份 月份 -->
<div class="month">
<ul>
<!--点击会触发pickpre函数,重新刷新当前日期 @click(vue v-on:click缩写) -->
<li class="arrow" @click="pickPre(currentYear,currentMonth)">❮</li>
<li class="year-month">
<span class="choose-year"
@click="pickYear(currentYear,currentMonth,1,$event)">{{ currentYear }}年</span>
<span class="choose-month"
@click="pickYear(currentYear,currentMonth,2,$event)">{{ currentMonth }}月</span>
<span>{{currentDay}}日</span>
</li>
<li class="arrow" @click="pickNext(currentYear,currentMonth)">❯</li>
</ul>
</div>
<!-- 星期 -->
<ul class="weekdays">
<li>一</li>
<li>二</li>
<li>三</li>
<li>四</li>
<li>五</li>
<li>六</li>
<li>日</li>
</ul>
<!-- 日期 -->
<ul class="days">
<!-- 核心 v-for循环 每一次循环用<li>标签创建一天 -->
<li v-for="dayobject in days" @click="changeDay(dayobject)" :key="dayobject.id"
:class="[{'other-month':!dayobject.isThisMonth},{'active':dayobject.isThisDay},{'this-month':dayobject.isThisMonth}]">
<span>{{ dayobject.day.getDate() }}</span>
</li>
</ul>
<div class="year-container" ref="container" v-if="showYearList">
<span v-for="(item,index) in yearList" :class="item==currentYear?'isYear':''" @click="selectYear(item)">{{item}}</span>
</div>
<div class="month-container" ref="container" v-if="showMonth">
<span v-for="(item,index) in month" :class="item==currentMonth?'isMonth':''" @click="selectMonth(item)">{{item}}</span>
</div>
</div>
var myVue = new Vue({
el: '#calendar',
data: {
currentDay: new Date().getDate(),
currentMonth: new Date().getMonth() + 1,
currentYear: new Date().getFullYear(),
currentWeek: 1,
days: [],
yearList: [],
showYearList: false,
month: null,
showMonth: false
},
created: function () { //在vue初始化时调用
var d = new Date()
this.initData(this.formatDate(d.getFullYear(), d.getMonth() + 1, d.getDate()));
},
mounted() {
this.isApp()
},
methods: {
initData: function (cur) {
this.days = []; //数据初始化
var date = new Date(cur);
this.currentDay = date.getDate();
this.currentYear = date.getFullYear();
this.currentMonth = date.getMonth() + 1;
this.currentWeek = date.getDay(); // 1...6,0
if (this.currentWeek == 0) this.currentWeek = 7; // 今天是周日,放在第一行第7个位置,前面6个
var thisMonthDays = new Date(this.currentYear, this.currentMonth, 0).getDate() //当月总天数
var thisMonthFirstDayIsWeeks = new Date(this.currentYear, this.currentMonth - 1, 1)
.getDay() == 0 ? 7 : new Date(this.currentYear, this.currentMonth - 1, 1)
.getDay() //当月第一天是周几,周日是0
var thisMonthLastDayIsWeeks = new Date(this.currentYear, this.currentMonth - 1,
thisMonthDays).getDay() == 0 ? 7 : new Date(this.currentYear, this
.currentMonth - 1, thisMonthDays).getDay() //当月最后一天是周几
// console.log("thisMonthDays:",thisMonthDays,";","thisMonthFirstDayIsWeeks:",thisMonthFirstDayIsWeeks,";","thisMonthLastDayIsWeeks:",thisMonthLastDayIsWeeks,";")
//上一个月
if (thisMonthFirstDayIsWeeks != 1) { //当月的第一天不是周一,需要补全前面的(上一个月的)天数
var y = this.currentMonth == 1 ? this.currentYear - 1 : this.currentYear
var m = this.currentMonth == 1 ? 12 : this.currentMonth - 1
var d = new Date(y, m, 0).getDate() //上一个月总天数
for (let i = 0; i < thisMonthFirstDayIsWeeks - 1; i++) { //判断上一个月是不是前一个年的最后一个月
var newD = new Date(y, m - 1, d - (thisMonthFirstDayIsWeeks - (i + 2)))
var dayobject = {};
dayobject.day = newD;
dayobject.isThisMonth = false
dayobject.isThisDay = false
this.days.push(dayobject);
}
}
//当前月
for (var i = 0; i < thisMonthDays; i++) {
var newD = new Date(this.currentYear, this.currentMonth - 1, i + 1)
var dayobject = {};
dayobject.day = newD;
dayobject.isThisMonth = true
dayobject.isThisDay = i + 1 == this.currentDay
this.days.push(dayobject);
}
//下一个月
if (thisMonthLastDayIsWeeks != 7) {
for (let i = 0; i < 7 - thisMonthLastDayIsWeeks; i++) { //判断下一个月是不是下一年的第一个月
var newD = new Date(this.currentMonth == 11 ? this.currentYear + 1 : this
.currentYear, this.currentMonth == 11 ? 0 : this.currentMonth, i + 1)
var dayobject = {};
dayobject.day = newD;
dayobject.isThisMonth = false
dayobject.isThisDay = false
this.days.push(dayobject);
}
}
},
pickPre: function (year, month) {
// setDate(0); 上月最后一天
// setDate(-1); 上月倒数第二天
// setDate(dx) 参数dx为 上月最后一天的前后dx天
if (month == 1) {
month = 12
year = year - 1
} else {
month = month - 1
}
this.initData(this.formatDate(year, month, 1));
},
pickNext: function (year, month) {
if (month == 12) {
month = 1
year = year + 1
} else {
month = month + 1
}
this.initData(this.formatDate(year, month, 1));
},
pickYear: function (year, month, type, e) {
var top = e.y + 32,
left = e.x - 120;
this.showMonth = false
this.showYearList = false
if (type == 1) {
this.yearList.length = 9
for (let i = 0; i < this.yearList.length; i++) {
if (i < 4) {
this.yearList[i] = year - (4 - i)
} else {
this.yearList[i] = year + (i - 4)
}
}
this.showYearList = true
} else {
this.showMonth = true
this.month = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
}
this.$nextTick(function () {
this.$refs.container.style = `top:${top}px;left:${left}px;`
})
},
// 返回 类似 2016-01-02 格式的字符串
formatDate: function (year, month, day) {
var y = year;
var m = month;
if (m < 10) m = "0" + m;
var d = day;
if (d < 10) d = "0" + d;
var data = y + "-" + m + "-" + d
return data
},
changeDay(dayobject) {
const dayDetail = dayobject.day
return dayDetail
},
selectYear(item){
this.showYearList = false
this.currentYear = item
this.initData(this.formatDate(this.currentYear,this.currentMonth,this.currentDay))
},
selectMonth(item){
this.showMonth = false
this.currentMonth = item
this.initData(this.formatDate(this.currentYear,this.currentMonth,this.currentDay))
},
isApp() {
// console.log(window.navigator)
if (window.navigator.userAgent.includes("Mobile")) {
this.$refs.calendar.style.width = "90%"
}
}
},
});
功能包括选择年份和月份
年份是当前年份前后各四个年份
因为这个是我日常写的东西没有在Vue项目中去使用,把这个迁移到Vue项目做为组件。
功能难点主要是当月的前一个月的日期和后一个月的日期的显示。在代码initDate()方法中实现
CSS方面使用grid布局和flex布局比较灵活。
仅供大家参考。
欢迎大家指点。