JavaScript小demo-日历


需求

实现下图中的日历,日历随着时间自动更新,当天的日期会用红底白字突出显示,点击“上一月”或“下一月”按钮,日期会随之变化,点击“回到当下”按钮,日期会回到当前时间。

分析

①变动的部分:年月日随着时间和操作的变化而变化

②不变的部分:“上一月”、“下一月”、星期、“回到当下”

思路

①变动的部分:写一个函数,输入为年、月、日,可以根据年月日实时更新dom节点,点击“上一月”按钮就计算上一月的年月日,点击“下一月”按钮就计算下一月的年月日,点击回到当下计算当前的年月日,点击过后都调用该函数根性dom节点

②不变的部分:写死,按钮添加一些事件

代码

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>Calendartitle>
    <style>
        ul,li {
            list-style: none;
            margin: 0;
            padding: 0;
        }

        html,body {
            width: 100%;
        }

        .data {
            width: 350px;
            display: flex;
            flex-direction: column;
            border: 1px solid gray;
            margin: 50px auto;
        }

        .data>div {
            display: flex;
        }

        .data>div>span {
            flex: 1;
        }

        .prevmonth {
            text-align: left;
        }

        .year {
            text-align: center;
        }

        .nextmonth {
            text-align: right;
        }

        .month {
            margin: auto;
            font-size: 13px;
            font-weight: bold;
        }

        .week {
            display: flex;
            background: rgb(175, 175, 175);
        }

        .week>li {
            flex: 1;
            text-align: center;
        }
        .day{
            display: flex;
            flex-wrap: wrap;
        }
        .day>li{
            width: 50px;
            height: 30px;
            text-align: center;
            line-height: 30px;

        }
        .back{
            border: none;
        }
    style>
head>

<body>
    <div class="data">
        <div>
            <span class="prevmonth">上一月span>
            <span class="year">2022span>
            <span class="nextmonth">下一月span>
        div>
        <div class="month">三月div>
        <ul class="week">
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
            <li>li>
        ul>

        <ul class="day">ul>
        <button class="back">回到当下button>
    div>

    <script>
        var date = new Date()                                       //获取当前时间戳
        var solar_calendar = date.toLocaleDateString().split('/')   //获取当前年、月、日
        var week = date.getDay()                                    //获取当前的星期
        var prevmonth = document.querySelector('.prevmonth')        //获取“上一月”dom节点,方便后面绑定事件
        var nextmonth = document.querySelector('.nextmonth')        //获取“下一月”dom节点
        var btn = document.querySelector('.back')                   //获取“回到当下”dom节点
        var num_to_week = ['一月','二月','三月','四月','五月','六月',  //根据数字索引可转化为中文月份的月份列表
            '七月','八月','九月','十月','十一月','十二月']

        plus(solar_calendar[0],solar_calendar[1],solar_calendar[2])//进入页面即调用修改dom的plus()函数,输入为当前的年月日

        //为“上一月”dom节点绑定点击事件
        prevmonth.onclick = function(){
            let year = document.querySelector('.year').innerHTML                            //获取当前年份的值
            let month = num_to_week.indexOf(document.querySelector('.month').innerHTML)+1   //获取当前月份的数值
            if(document.querySelector('.month').innerHTML==='一月'){                        //判断当前月份是否为一月
                year = year - 1                                                             //是的话,点击之后年份减1,月份变为12
                month = 12
                if(year==solar_calendar[0]&&month==solar_calendar[1]){                      //判断年、月是否是当前的年、月,加这个判断是为了给当前年月的日期加一个红底白字的渲染
                    plus(year,month,solar_calendar[2])                                      //是的话调用plus()函数
                }else{
                    plus(year,month)                                                        //不是的话调用plus()函数,其中day默认值为0,这样就不会对日期进行渲染
                }
            }else{                                                                          //当前日期不是一月则月份减1
                month = month - 1
                if(year==solar_calendar[0]&&month==solar_calendar[1]){                      //判断年、月是否是当前的年、月
                    plus(year,month,solar_calendar[2])                                      //是的话调用plus()函数
                }else{
                    plus(year,month)                                                         //不是的话调用plus()函数,其中day默认值为0,这样就不会对日期进行渲染
                }
            }
        }

        // 为“下一月”绑定点击事件,流程和“上一月”都差不多了
        nextmonth.onclick = function(){
            let year = document.querySelector('.year').innerHTML
            let month = num_to_week.indexOf(document.querySelector('.month').innerHTML)+1
            if(document.querySelector('.month').innerHTML==='十二月'){
                year = String(parseInt(year) + 1)
                month = 1
                if(year==solar_calendar[0]&&month==solar_calendar[1]){
                    plus(year,month,solar_calendar[2])
                }else{
                    plus(year,month)
                }
            }else{
                month = month + 1
                if(year==solar_calendar[0]&&month==solar_calendar[1]){
                    plus(year,month,solar_calendar[2])
                }else{
                    plus(year,month)
                }
            }
        }

        // 为“回到当下”绑定点击事件,调用plus()函数,输入为当前年、月、日
        btn.onclick = function(){
            plus(solar_calendar[0],solar_calendar[1],solar_calendar[2])
        }

        //获取闰年和非闰年每月的日期数
        function Leap_year(year){
            if(!(year%400)||!(year%4)&&year%100){               //判断是否为闰年
                return [31,29,31,30,31,30,31,31,30,31,30,31]    //是的话返回二月为29天的数组
            }
            return [31,28,31,30,31,30,31,31,30,31,30,31]        //不是的话返回二月为28天的数组
        }

        //动态渲染节点函数,输入为年、月、日
        function plus(year,month,day=0) {
            
            //修改年份和月份为输入的年份和月份
            document.querySelector('.year').innerHTML = year
            document.querySelector('.month').innerHTML = num_to_week[month-1]
            
            //调用Leap_year得到输入年份的每月天数的数组
            let days_of_month = Leap_year(year)
            var str = ''

            // 得到每月1号的星期数,并在每月1号前面添加相应数量空的li节点
            for(let j=0;j<parseInt(new Date(year,month-1,1).getDay());j++){
                str = str + '
  • ' } // 根据输入月的天数动态增加li节点 for(let i=1; i<days_of_month[month-1]+1; i++){ // 判断输入的day是否等于i,是的话就渲染节点,不是当前年月时输入的day默认为0就不会渲染 if(day==i){ str = str + "
  • "+i+"
  • " } else{ str = str + '
  • '+i+'
  • ' } } document.querySelector('.day').innerHTML = str } script> body> html>