方案一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk="
crossorigin="anonymous"></script>
<style>
* {
margin: 0;
padding: 0;
}
.container {
width: 800px;
margin: 50px auto;
}
.week-day {
display: flex;
}
.week {
flex: 0 0 14%;
text-align: center;
}
.days {
display: flex;
flex-wrap: wrap;
}
.day {
flex: 0 0 14%;
height: 60px;
/* background-color: cyan; */
display: flex;
align-items: center;
justify-content: center;
}
.day:hover {
background-color: #f5f5f5;
}
.day.active {
background-color: cyan;
}
.df {
display: flex;
}
.fsb {
display: flex;
justify-content: space-between;
}
.btn {
margin-right: 30px;
}
.next {
margin-left: 30px;
}
</style>
</head>
<body>
<div class="container df fsb" style="padding: 0 100px;">
<div class="btn preview">上个月</div>
<div class="date"></div>
<div class="btn next">下个月</div>
</div>
<div class="container">
<div class="week-day">
<div class="week">星期一</div>
<div class="week">星期二</div>
<div class="week">星期三</div>
<div class="week">星期四</div>
<div class="week">星期五</div>
<div class="week">星期六</div>
<div class="week">星期日</div>
</div>
<div class="days">
</div>
</div>
<script>
class Calendar{
constructor({date:dateStr='',container=null}) {
this.dateStr = dateStr
this.date = this.dateStr? new Date(this.dateStr) :new Date()
this.container = document.querySelector(container)
if(!container) {
throw new Error('container is required')
}
this.init()
}
init() {
this.year = this.date.getFullYear()
this.month = this.date.getMonth()+1
this.weekDay = this.date.getDay()
this.days = this.getMonthDays()
this.isToday = this.checkIsToday()
this.render()
}
checkIsToday(day) {
let date = new Date()
return date.getFullYear()==this.year && this.month==(date.getMonth()+1) &&day==date.getDate()
}
getMonthDays() {
return new Date(this.year, this.month, 0).getDate()
}
render() {
let str = ''
if (this.weekDay >= 1) {
str = `<div class="day"></div>`.repeat(this.weekDay - 1)
}else {
str = `<div class="day"></div>`.repeat(6)
}
for (let i = 1; i <= this.days; i++) {
str += `<div class="day ${this.checkIsToday(i)?'active':''}" >${i}</div>`
}
let total = this.weekDay == 0?this.days+6: this.weekDay-1 + this.days
if(total<42) {
str += `<div class="day"></div>`.repeat(42-total)
}
this.container.innerHTML= str
}
getCurrent() {
return `${this.year}-${this.month}`
}
lastMonth() {
if(this.month==1) {
this.month = 12
this.year = this.year-1
}else {
this.month --
}
this.date = new Date(`${this.year}-${this.month}-1`)
this.init()
}
nextMonth() {
if (this.month == 12) {
this.month = 1
this.year = this.year + 1
} else {
this.month++
}
this.date = new Date(`${this.year}-${this.month}-1`)
this.init()
}
}
$(function() {
let container = $('.container')
let calendar = new Calendar({container:'.days'})
$('.date').text(calendar.getCurrent())
$('.preview').click(()=> {
calendar.lastMonth()
$('.date').text(calendar.getCurrent())
})
$('.next').click(()=> {
calendar.nextMonth()
$('.date').text(calendar.getCurrent())
})
})
</script>
</body>
</html>
方案2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.app {
width: 700px;
}
.week {
display: flex;
align-items: center;
}
.week-item {
width: 100px;
height: 50px;
text-align: center;
line-height: 50px;
background-color: #f5f5f5;
}
.daybox {
display: flex;
flex-wrap: wrap;
}
.day {
width: 100px;
height: 50px;
text-align: center;
line-height: 50px;
}
.day.cur {
color: red;
}
.day.before,
.day.after {
color: #ccc;
}
.title {
display: flex;
align-items: center;
}
.pre,
.next {
width: 50px;
height: 50px;
text-align: center;
line-height: 50px;
font-size: 18px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="title">
<div class="pre">
< </div>
<div class="current"></div>
<div class="next">></div>
</div>
<div class="app">
<div class="week">
<div class="week-item">1</div>
<div class="week-item">2</div>
<div class="week-item">3</div>
<div class="week-item">4</div>
<div class="week-item">5</div>
<div class="week-item">6</div>
<div class="week-item">7</div>
</div>
<div class="week daybox">
</div>
</div>
<script>
class Calendar {
constructor(data) {
let date = new Date(data)
this.year = date.getFullYear()
this.curMonth = date.getMonth() + 1
this.curDay = date.getDay()
this.month = []
this.monthDay = {}
this.genMonth()
this.render()
}
isLeapYear() {
return this.year % 4 == 0 && this.year % 100 != 0 || this.year % 400 == 0
}
genMonth() {
this.month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
if (this.isLeapYear()) {
this.month[1] = 29
}
}
render() {
this.monthFirstDay = new Date(`${this.year}-${this.curMonth}-1`).getDay()
this.first = this.monthFirstDay == 0 ? 7 : this.monthFirstDay
let day = this.getBefore().concat(this.getMonthArr(), this.getAfter())
let str = ''
day.forEach(item => {
str += `<div class="day ${item.flag} ${this.isCurrent(item.day) ? 'cur' : ''}">${item.day}</div>`
})
let box = document.querySelector('.daybox')
box.innerHTML = str
this.renderCurrent()
}
renderCurrent() {
let cur = document.querySelector('.current')
cur.innerHTML = this.getCurrent()
}
getMonthArr() {
let len = this.month[this.curMonth - 1]
let arr = []
for (let i = 1; i <= len; i++) {
arr.push({ day: i, flag: 'month' })
}
return arr
}
getBefore() {
let len = this.first - 1
let index = this.curMonth == 12? 10: this.curMonth
let before = this.month[index]
let arr = []
while (len > 0) {
arr.push({ day: before, flag: 'before' })
before--
len--
}
arr.sort((a, b) => a.day - b.day)
return arr
}
getAfter() {
let endDay = new Date(`${this.year}-${this.curMonth}-${this.month[this.curMonth - 1]}`).getDay()
let len = 7 - endDay == 0 ? 0 : 7 - endDay
let total = this.getMonthArr().length + this.getBefore().length
if (total < 35) {
len = len + 7
}
let arr = []
for (let i = 1; i <= len; i++) {
arr.push({ day: i, flag: 'after' })
}
return arr
}
isCurrent(day) {
let date = new Date()
return date.getFullYear() == this.year && (date.getMonth() + 1) == this.curMonth && date.getDate() == day
}
getCurrent() {
return `${this.year} - ${this.curMonth}`
}
pre() {
let m = this.curMonth - 1
if (m == 0) {
this.curMonth = 12
this.year = this.year - 1
} else {
this.curMonth = this.curMonth - 1
}
this.render()
}
next() {
let m = this.curMonth + 1
if (m > 12) {
this.curMonth = 1
this.year = this.year + 1
} else {
this.curMonth = this.curMonth + 1
}
this.render()
}
}
let demo = new Calendar(new Date())
let pre = document.querySelector('.pre')
let next = document.querySelector('.next')
pre.onclick = function (e) {
demo.pre()
}
next.onclick = function (e) {
demo.next()
}
</script>
</body>
</html>