問題描述: 通過改變文字框裡的日期,改變日曆,同時日曆上有一些資料展示
1, 顯示效果圖 (以文字框裡選中的2018年9月為例)
- 顯示當前月
- 上一個月和下一個月灰色補全顯示
- 可以在日曆裡面展示一些描述
2, 方法一: 程式碼如下(文章基於vue寫的,寫好dom渲染資料)
- html程式碼
<template>
<div>
<div>
選擇時間:
<DatePicker type="date" style="width: 180px;" @on-change="ChangeTime" v-model="valueData"></DatePicker>
</div>
<table class="week-wrapper">
<tr>
<td class="c-red">星期日</td>
<td>星期一</td>
<td>星期二</td>
<td>星期三</td>
<td>星期四</td>
<td>星期五</td>
<td class="c-red">星期六</td>
</tr>
</table>
<div>
<ul class="calendar-wrapper">
<!-- 顯示上個月 -->
<li v-for="(item, index) in timeStart" :key="index+'a'" class="calendar-li">
<div class="calendar-div">
<span class="calendar-span " style="color:#ccc">{{(beforeMonthLength - timeStart + item)}}</span>
</div>
</li>
<!-- 顯示本月 -->
<li v-for="(n, ind) in timeLast" :key="ind+'b'" class="calendar-li">
<!-- 通過if 條件 判斷 給當前選中的日期新增背景 -->
<div v-if="timeD == n" class="calendar-div currentColor">
<span class="calendar-span">{{n}}</span>
</div>
<div v-else class="calendar-div">
<span class="calendar-span">{{n}}</span>
</div>
</li>
<!-- 顯示下個月個月 -->
<!-- 通過if 條件 判斷 如果結束日期是0,下個月的會再顯示一行,這個不需要 -->
<li v-if="timeEnd>0" v-for="(i, inde) in (7 - timeEnd)" :key="inde+'c'" class="calendar-li">
<div class="calendar-div">
<span class="calendar-span" style="color:#ccc">{{i}}</span>
<div class="calendar-desc">
<p>今日待辦:2</p>
</div>
</div>
</li>
</ul>
</div>
</div>
</template>
複製程式碼
- ts程式碼
<script lang='ts'>
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class WorkDesk extends Vue {
timeLast: any = ''
timeStart: any = ''
timeEnd: any = ''
beforeMonthLength: any = ''
valueData: any = ''
timeY: any = ''
timeM: any = ''
timeD: any = ''
getMonthTr: any = ''
strMonths: any = ''
created () {
let currentTime = new Date()
this.valueData = currentTime // 最開始給文字框賦值,當前系統
this.getcurrenttime(currentTime)
}
mounted () {
this.setDate()
}
getcurrenttime (timestr) {
let dat = timestr ? new Date(timestr) : new Date()
this.timeY = dat.getFullYear().toString()
this.timeM = dat.getMonth().toString()
this.timeD = dat.getDate().toString()
}
setDate () {
let mth = Number(this.timeM) // 數字化
let first = new Date(this.timeY, mth, 1) // 當月開始日期
this.timeStart = first.getDay() // 當月開始星期
let last = new Date(this.timeY, mth + 1, 0) // 當月結束時間
this.timeLast = last.getDate()
let end = new Date(this.timeY, mth + 1, 1) // 下個月開始日期
this.timeEnd = end.getDay() // 下個月開始的星期
let beforeMonth = new Date(this.timeY, mth, 0)
this.beforeMonthLength = beforeMonth.getDate()
}
// 通過文字框選擇時間
ChangeTime (timestr) {
this.getcurrenttime(timestr)
this.setDate()
}
}
</script>
複製程式碼
- css程式碼
<style scoped>
.c-red{
color: red;
}
.week-wrapper{
width: 100%;
height: 36px;
line-height: 36px;
text-align: center;
}
.calendar-li{
width: 14.28%;
float: left;
}
.calendar-div{
position: relative;
background: #fff;
margin: 2px;
height: 88px;
}
.calendar-span{
position: absolute;
top:10px;
right: 10px;
font-size: 20px;
}
.calendar-desc{
position: absolute;
bottom:10px;
left: 5px;
}
.currentColor{
background: #0ff0ff;
}
</style>
複製程式碼
3, 方法二: (直接渲染dom)
- html程式碼
<template>
<div>
<div>
選擇時間:
<DatePicker type="date" style="width: 180px;" @on-change="ChangeTime" v-model="valueData"></DatePicker>
</div>
<table class="week-wrapper">
<tr>
<td class="c-red">星期日</td>
<td>星期一</td>
<td>星期二</td>
<td>星期三</td>
<td>星期四</td>
<td>星期五</td>
<td class="c-red">星期六</td>
</tr>
</table>
<div>
<ul class="calendar-wrapper">
</ul>
</div>
</div>
</template>
複製程式碼
- ts程式碼
<script lang='ts'>
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class WorkDesk extends Vue {
timeLast: any = ''
timeStart: any = ''
timeEnd: any = ''
beforeMonthLength: any = ''
valueData: any = ''
html: any = ''
timeY: any = ''
timeM: any = ''
timeD: any = ''
getMonthTr: any = ''
strMonths: any = ''
created () {
let a = new Date()
this.valueData = a
this.getcurrenttime(a)
}
mounted () {
this.setDate()
}
getcurrenttime (timestr) {
let dat = timestr ? new Date(timestr) : new Date()
this.timeY = dat.getFullYear().toString()
this.timeM = dat.getMonth().toString()
this.timeD = dat.getDate().toString()
}
setDate () {
let mth = Number(this.timeM)
let first = new Date(this.timeY, mth, 1) // 當月開始日期
this.timeStart = first.getDay() // 當月開始星期
let last = new Date(this.timeY, mth + 1, 0) // 當月結束時間
this.timeLast = last.getDate()
let end = new Date(this.timeY, mth + 1, 1) // 下個月開始日期
this.timeEnd = end.getDay() // 下個月開始的星期
let beforeMonth = new Date(this.timeY, mth, 0)
this.beforeMonthLength = beforeMonth.getDate()
let myStr = ''
// 前面的日期
for (let i = 0; i < timeStart; i++) {
myStr +=
`<li class="calendar-li"><div class="calendar-div">
<span>${(beforeMonthLength - timeStart + i + 1)}</span>
</div></li>`
}
// 當前日期
for (let i = 1; i <= timeLast; i++) {
let iMax = (i < 10) ? `0${i}` : i
myStr += '<li id="attendance_' + i + '"><div class="calendar-div">' +
'<span>' + iMax + '</span>' +
'</div></li>'
}
// 後面的日期
for (let i = 0; i < 7 - timeEnd; i++) {
myStr += `
<li class="classObject"><div class="calendar-div">
<span>0${i + 1}</span>
</div></li>`
}
this.html = myStr
}
ChangeTime (timestr) {
this.getcurrenttime(timestr)
this.setDate()
}
}
</script>
複製程式碼
- css樣式,這個li的樣式可以寫在行內,如果不寫在行內,需要通過>>>來渲染
<style scoped>
/* 寫一點給個說明,樣式和上面第一種方法一樣 */
.calendar-wrapper >>> .calendar-li
width: 14.28%;
float: left;
}
.calendar-wrapper >>> .calendar-div{
position: relative;
background: #fff;
margin: 2px;
height: 88px;
}
</style>
複製程式碼
4, 方法三: (通過42格固定來渲染,可以顯示42個,也可以按需求顯示) 程式碼和上面的類似,只寫改變的部分程式碼
- html程式碼(只有ul渲染的那一部分改變了,只貼上這一部分)
<ul class="calendar-wrapper">
<li v-for="(item, index) in CalendarDays" :key="index" class="calendar-li">
<div class="calendar-div" :class="{'is-class': currentData === item.day}">
<span class="calendar-span" v-if="item.type==='current'">{{item.day}}</span>
<div v-else>
<!-- <span class="calendar-desc">一些描述</span> -->
<span class="calendar-span" style="color: #ccc;">{{item.day}}</span>
</div>
</div>
</li>
</ul>
複製程式碼
- ts程式碼(一些命名跟上面的不一樣,修改了,看的時候注意一下)
<script lang='ts'>
import Vue from 'vue'
import Component from 'vue-class-component'
@Component
export default class WorkDesk extends Vue {
valueData: any = ''
CalendarDays: any = []
currentYear: any = ''
currentMouth: any = ''
currentData: any = ''
isAA = false
created () {
let currentTime = new Date()
this.valueData = currentTime // 文字框裡的時間
this.getInputValue(currentTime)
}
mounted () {
this.getCalendarData()
}
// 改變下拉的時間的值
ChangeTime (timestr) {
this.getInputValue(timestr)
this.getCalendarData()
}
// 處理獲取的時間,轉換成20180901這種格式
getDateStr (date) {
var timeY = date.getFullYear()
var timeM = date.getMonth()
var timeD = date.getDate()
timeM = (timeM > 9) ? timeM : ('0' + timeM)
timeD = (timeD > 9) ? timeD : ('0' + timeD)
return `${timeY}${timeM}${timeD}`
}
// 獲取值,當前年月或者文字框裡的值
getInputValue (timestr) {
let dat = timestr ? new Date(timestr) : new Date()
this.currentYear = dat.getFullYear()
this.currentMouth = dat.getMonth()
this.currentData = dat.getDate()
}
// 生成日曆時間
getCalendarData () {
let dayArr = []
let _firstData = new Date(this.currentYear, this.currentMouth, 1) // 當前月第一天
let startWeek = _firstData.getDay() // 當前月開始的星期
for (var i = 0; i < 42; i++) {
let _AllDay = new Date(this.currentYear, this.currentMouth, i + 1 - startWeek) // 所有迴圈出來的時間,一共42個
let _AllDayStr = this.getDateStr(_AllDay)
// let isFuture = _AllDay.getTime() > Date.now() // 未來為true,今天昨天為false
// let isTodayFuture = _AllDay.getTime() > Date.now() - 8.64e7 // 未來和今天為true
// let month = _AllDay.getMonth() + 1 > 9 ? _AllDay.getMonth() + 1 : '0' + (_AllDay.getMonth() + 1)
// let daaa = _AllDay.getDate() > 9 ? _AllDay.getDate() : ('0' + _AllDay.getDate())
// getDateStr(_firstData),處理當前月,跟獲取的所有日期進行對比
if (_AllDayStr.substr(0, 6) === this.getDateStr(_firstData).substr(0, 6)) {
dayArr.push({
type: 'current',
isFuture: isFuture, // 比較日期的時候會用到
isTodayFuture: isTodayFuture,
year: _AllDay.getFullYear(),
month: month,
daaa: daaa,
day: _AllDay.getDate()
})
} else if (_AllDayStr.substr(0, 6) < this.getDateStr(_firstData).substr(0, 6)) {
dayArr.push({
type: 'before',
isFuture: isFuture,
isTodayFuture: isTodayFuture,
year: _AllDay.getFullYear(),
month: month,
daaa: daaa,
day: _AllDay.getDate()
})
} else {
if (_AllDay.getDay() === 0) { // 如果日曆只是補全,下個月的最多顯示6個,不再重新起一行顯示
break
}
dayArr.push({
type: 'after',
isFuture: isFuture,
isTodayFuture: isTodayFuture,
year: _AllDay.getFullYear(),
month: month,
daaa: daaa,
day: _AllDay.getDate()
})
}
}
this.CalendarDays = dayArr
console.log(dayArr)
}
}
</script>
<style scoped>
複製程式碼
注意:如果這行程式碼去掉
if (_AllDay.getDay() === 0) { // 如果日曆只是補全,下個月的最多顯示6個,不再重新起一行顯示 break }
效果圖如下:(固定的42格顯示,如果加上這一句程式碼,下面的5號到11號是不顯示的,值補全了1號到4號)
-
如有問題,歡迎指正
-
本文為原創,如需轉載,請註明出處: js手寫日曆