原生js之实现一个日历弹出框

原生js之实现一个日历弹出框

实现功能:

点击输入框,弹出选择日期,显示当前年月日,当前日期背景为蓝色,字体为白色。
再次点击输入框,日期选择框消失。
点击选中日期,弹出框消失,输入框显示选中日期。

功能拆解

   1. 一个input框,绑定点击事件。
   2. 一个前一个月按钮,点击显示前一个月的日期,一个下一个月的按钮,点击显示下一个月的日期。
   3. 弹出框header部分默认显示当前年月日,选择时显示选择的年月日。body部分,展示日期天数。

日期表格渲染思路

getMultidimensionalArrayByDay 函数 接收一个当前年和一个当前月共两个参数。返回一个包含年月日的多维数组。
getDayNumsByMonth 函数 接收一个月份参数,返回当前月天数。

代码部分

html

   <div class="date-box">
      <input type="text" placeholder="请输入日期" class="date-input" />
      <div class="date">
        <div class="date-header">
          <div class="pre-date"><<</div>
          <div class="show-year-month"></div>
          <div class="next-date">>></div>
        </div>
        <table class="date-table">
          <thead>
            <tr>
              <th></th>
              <th></th>
              <th></th>
              <th></th>
              <th></th>
              <th></th>
              <th></th>
            </tr>
          </thead>
          <tbody class="date-tbody"></tbody>
        </table>
      </div>
    </div>

css部分

   <style>
      .date-box {
        width: 280px;
        height: 300px;
        position: relative;
        overflow: hidden;
        color: #606266;
      }
      .date-box input {
        width: 100%;
        height: 32px;
        box-shadow: 2px 2px 5px #eee;
        border-radius: 4px;
        border: 1px solid #eee;
        box-sizing: border-box;
        text-align: center;
        outline: none;
      }
      .date-box .date {
        width: 100%;
        height: calc(100% - 40px);
        box-shadow: 2px 2px 5px #ccc;
        border-radius: 4px;
        border: 1px solid #eee;
        position: absolute;
        left: 0;
        top: 40px;
        box-sizing: border-box;
        display: none;
      }
      .date-box .date .date-header {
        width: 100%;
        height: 30px;
        display: flex;
        justify-content: space-around;
        align-items: center;
      }
      .date-box .date-table {
        width: 100%;
        height: calc(100% - 30px);
      }
      .date-box .date-table tr td {
        border-collapse: collapse;
      }
      .date-box .date-table thead {
        width: 100%;
        height: 30px;
      }
      .date-box .date-table thead tr {
        width: 100%;
        height: 100%;
      }
      .date-box .date-table tbody {
        width: 100%;
        height: calc(100% - 30px);
      }
      .date-box .date-table tbody tr {
        text-align: center;
        vertical-align: middle;
      }
      .date-box .date-table tbody tr td:hover {
        color: #409eff;
      }
    </style>

js

      let date = new Date() //日期对象
      let currentYear = date.getFullYear() // 当前年
      let currentMonth = date.getMonth() // 当前月
      let currentDate = date.getDate() // 当前日
      let setCurrentDateFlag = false // 是否设置了当前日背景,默认为false
      let selectDate = '' //选中日期
      // 展示年月日
      $('.show-year-month').textContent = `${currentYear}${currentMonth + 1}`
      // 上个月按钮
      $('.pre-date').onclick = function () {
        currentMonth = currentMonth - 1
        // 当当前月小于0,将当前月设置为11月
        if (currentMonth < 0) {
          currentMonth = 11
          currentYear = currentYear - 1
        }
        $('.show-year-month').textContent = `${currentYear}${currentMonth + 1}`
        setCurrentDateFlag = false
        getMultidimensionalArrayByDay(currentYear, currentMonth)
      }
      // 下个月按钮
      $('.next-date').onclick = function () {
        currentMonth = currentMonth + 1
        // 当当前月大于12,将当前月重置为1
        if (currentMonth > 12) {
          currentMonth = 1
          currentYear = currentYear + 1
        }
        $('.show-year-month').textContent = `${currentYear}${currentMonth + 1}`
        setCurrentDateFlag = false
        getMultidimensionalArrayByDay(currentYear, currentMonth)
      }
      // 日期选择框input
      $('.date-input').onclick = function () {
        if ($('.date').style.display == 'none' || !$('.date').style.display) {
          $('.date').style.display = 'inline-block'
          observeTdClick()
        } else {
          $('.date').style.display = 'none'
        }
      }
      // 获取年月日数组
      function getMultidimensionalArrayByDay(currentYear, currentMonth) {
        // 清除dom,重新渲染表格
        let trList = Array.from($('.date-tbody').children)
        if (trList && trList.length) {
          trList.map(item => {
            $('.date-tbody').removeChild(item)
          })
        }
        let d = new Date(currentYear, currentMonth)
        d.setDate(1)
        let startDay = d.getDay()
        let count = 0
        let nextPreMonthCount = 0
        let multidimensionalArray = []
        // 一共有6个tr,6行
        for (let i = 0; i < 6; i++) {
         // 设置列数 这里是7列
          let dayColumnList = new Array(7)
          if (i === 0) {
            //  第一行  startDay 当前月的第一天是周几 假设 startDay = 5  那么 j = 4  
            // dayColumnList.length 7           
            // [,,,,1,2,3]
            for (let j = startDay - 1; j < dayColumnList.length; j++) {
              dayColumnList[j] = ++count
            }
          } else {
            // 按照上述假设,此时count = 4, dayColumnList.length = 7  0,1,2,3,4,5,6
            for (let j = 0; j < dayColumnList.length; j++) {
              count++
              // 按照上述假设, getDayNumsByMonth(d.getMonth())返回值为31
              // 超过当前月天数,开始下个月天数加1填充
              if (count > getDayNumsByMonth(d.getMonth())) {
                dayColumnList[j] = ++nextPreMonthCount
              } else {
                // 没超过当前月天数的情况
                dayColumnList[j] = count
              }
            }
          }
          multidimensionalArray.push(dayColumnList)
        }
        // 填充第一行为空的日期
        let preMonthDayNums = getDayNumsByMonth(d.getMonth() - 1)
        for (let k = d.getDay() - 2; k >= 0; k--) {
          multidimensionalArray[0][k] = preMonthDayNums--
        }
        let nextMonthNums = getDayNumsByMonth(d.getMonth() + 1)
        let realCurrentYear = date.getFullYear()
        let realCurrentMonth = date.getMonth()
        // 渲染表格
        for (let q = 0; q < multidimensionalArray.length; q++) {
          let tr = document.createElement('tr')
          let item = multidimensionalArray[q]
          for (let m = 0; m < item.length; m++) {
            let td = document.createElement('td')
            td.textContent = item[m]
            // 当前年月日背景色为蓝色,颜色为白色
            if (!setCurrentDateFlag && item[m] === currentDate && realCurrentYear === currentYear && realCurrentMonth === currentMonth) {
              td.style.backgroundColor = 'blue'
              td.style.color = 'white'
              setCurrentDateFlag = true
            }
            tr.appendChild(td)
          }
          $('.date-tbody').appendChild(tr)
        }
      }
      // 获取一个月有多少天
      function getDayNumsByMonth(currentMonth) {
        let d = new Date()
        d.setMonth(currentMonth + 1)
        d.setDate(0) // 可以获取一个月有多少天
        let dayNums = d.getDate()
        return dayNums
      }
      // 监听点击选择日期事件
      function observeTdClick() {
        let tdList = Array.from(document.getElementsByTagName('td'))
        tdList.forEach(td => {
          td.onclick = function () {
            let day = td.textContent
            selectDate = `${currentYear}-${currentMonth + 1}-${day}`
            $('.date-input').value = selectDate
            $('.date').style.display = 'none'
          }
        })
      }
      function $(selector) {
        return document.querySelector(selector)
      }
      getMultidimensionalArrayByDay(currentYear, currentMonth)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值