js手写日历

问题描述: 通过改变文本框里的日期,改变日历,同时日历上有一些数据展示


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手写日历

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值