资讯专栏INFORMATION COLUMN

微信小程序:手写日历组件

genefy / 1808人阅读

摘要:一前言最近公司要做一个酒店入住的小程序,不可避免的一定会使用到日历,而小程序没有内置的日历组件。二代码原理分析写一个日历只需要知道两件事情一个月有多少天每个月的第一天是星期几。

一、前言

最近公司要做一个酒店入住的小程序,不可避免的一定会使用到日历,而小程序没有内置的日历组件。在网上看了一下也没有非常适合需求的日历,于是自己写了一个。

二、代码 1. 原理分析

写一个日历只需要知道两件事情:

一个月有多少天;

每个月的第一天是星期几。

2. 功能分析

由于是酒店入住的日历,所以需要实现如下功能:

渲染日历,一般是从本月开始,到半年之后的日历

过去的日期不可选

实现点击获取入住日期、退房日期,以及改变相应日期的颜色和整个时间段的颜色

3. 数据分析

根据最后的功能实现,我生成的每个月的数据结构如下:

{
    year: 2018,
    month: 3,
    fullMonth: "03",
    allDays:[
        {
            day: 1,
            fullDay: "01",
            fullDate: "2018-03-01"
        },
        {
            day: 2,
            fullDay: "02",
            fullDate: "2018-03-02"
        },
        //......
        //(后面的数据同上)
    ]
}

year就是年份,month是月份,day是日期,fullDate是完整日期。
fullMonth和fullDay原本是两个不需要的数据,但是在点击日期改变颜色的时候用到了,因为小程序没有提供很好的处理数据的filter。当然这个问题也和我的个人水平有关,如果有哪位大神有更好的方法,请留言告诉我。我非常想去掉这两个数据。

4.代码分析
// calendar.js文件

Page({
  data: {
    week_list: ["日","一","二","三","四","五","六"],
    startDate: "",
    endDate: "",
    date_click: 0
  },
  // 获取每月总天数
  getAllDaysOfMonth(year,month) {
    return new Date(year,month,0).getDate();
  },
  // 获取每月第一天是星期几
  getFirstDayOfMonth(year,month) {
    return new Date(year, month - 1, 1).getDay();
  },
  // 计算本月前空了几格
  getEmptyGrids(year,month) {
    // FirstDayOfMonth代表本月的第一天是星期几
    const FirstDayOfMonth = this.getFirstDayOfMonth(year, month);
    let emptyGrids = [];
    
    // 有空格的情况
    if (FirstDayOfMonth > 0) {
      for (let i = 0; i < FirstDayOfMonth; i++) {
        emptyGrids.push({
          "num": "",
          "fullDate": "x"  //x是我自己定义的一个值,代表没有日期
        });
      }
      // 将空格放入数组
      return emptyGrids;
    }else{
      // 否则返回一个新数组
      return [];
    }
  },
  // 计算本月日历
  getDaysOfThisMonth(year,month) {
    let days = [];
    const AllDaysOfMonth = this.getAllDaysOfMonth(year, month);

    let fullMonth = month.toString().length === 1 ? `0${month}`:month;
    for (let i = 0; i < AllDaysOfMonth; i++) {
      let day = i+1,
          fullDay = day;

      fullDay = fullDay.toString().length === 1 ? `0${day}` : fullDay;
      days.push({
        day,
        fullDay,
        "fullDate": `${year}-${fullMonth}-${fullDay}`
      });
    }
    // 返回每个月的具体日期
    return days;
  },
  // 循环渲染日历
  // 从本月开始渲染,n代表包括本月开始连续渲染几个月
  fillCalendar(n) {
    let year = this.data.cur_year,
        month = this.data.cur_month,
        fullMonth,
        canlendar_data = [];

    // 计算年月以及具体日历
    for (let i = this.data.cur_month; i < this.data.cur_month + n; i++) {
      let EmptyGrids = this.getEmptyGrids(year, month);
      let DaysOfThisMonth = this.getDaysOfThisMonth(year, month);

      // 把空格和具体日历合为一个数组
      let allDays = [...EmptyGrids, ...DaysOfThisMonth];

      // 对年份和月份的计算做一些判断
      if (month > 12) {
        year++;
        month = 1;
        fullMonth = "01"
        canlendar_data.push({
          year, 
          month, 
          fullMonth,
          allDays });
        month++;
      }else{
        fullMonth = month.toString().length === 1 ? `0${month}` : month;
        canlendar_data.push({ 
          year, 
          month, 
          fullMonth,
          allDays });
        month++;
        
      }

    }

    this.setData({
      canlendar_data
    })
  },
  onLoad() {
    const date = new Date();
    const cur_year = date.getFullYear();
    const cur_month = date.getMonth() + 1;
    const cur_day = date.getDate();
    this.setData({
      date,
      cur_year,
      cur_month,
      cur_day
    })

    let month = this.data.cur_month.toString().length === 1 ? `0${this.data.cur_month}` : this.data.cur_month;
    let day = this.data.cur_day.toString().length === 1 ? `0${this.data.cur_day}` : this.data.cur_day;
    let nowDate = `${cur_year}-${month}-${day}`;

    this.setData({
      nowDate
    })

    this.fillCalendar(6);
  },
  // 点击日期
  chooseDate(e) {
    const year_click = e.currentTarget.dataset.year;
    const month_click = e.currentTarget.dataset.month;
    const day_click = e.currentTarget.dataset.day;
    console.log(year_click,month_click,day_click);
    // 如果是空格或者以前的日期就直接返回
    if(day_click === ""||`${year_click}-${month_click}-${day_click}` < this.data.nowDate) {
      return;
    }

    // 获取点击对象的id
    let id = e.currentTarget.dataset.id;
    
    // data_click为0代表选择的是入住日期,否则就是离店日期
    if (this.data.date_click == 0){
      // 选择入住日期
      this.setData({
        startDate: `${year_click}-${month_click}-${day_click}`,
        date_click: 1
      })
    }else {
      let newDay = new Date(Date.parse(id));
      let oldDay = new Date(Date.parse(this.data.startDate));

      // 判断第二次点击的日期在第一次点击的日期前面还是后面
      if (newDay > oldDay) {
        this.setData({
          endDate: `${year_click}-${month_click}-${day_click}`,
          date_click: 2
        })
      }else{
        this.setData({
          startDate: `${year_click}-${month_click}-${day_click}`,
          endDate: "",
          date_click: 1
        })
      }
    }
  }
})



  
    {{item}}
  
  
    
      {{canlendar_item.year}}年{{canlendar_item.month}}月
      
        startDate&&item.fullDate{{item.day}}
      
    
  

{{idx===0||idx===6?"relax":""}} 是改变周六周日的颜色,
{{item.fullDate{{startDate===item.fullDate?"startActive":""}} 判断点击的是入住日期,
{{endDate===item.fullDate?"endActive":""}} 判断点击的是离店日期,
{{item.fullDate>startDate&&item.fullDate 四、结语

到此一个简单的日历就完成了,当然这个日历无法满足所有业务需求,但是基本的日历渲染功能以及点击选择功能都有。所以在业务需求之上对其进行小部分改变就可以了,希望大家可以留言指出我的问题,我也会进一步的改善这个日历代码。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93094.html

相关文章

  • 简陋至极:信小程序日历组件(思路)

    摘要:最近在做微信小程序项目,其中涉及到日历。其次,弄清楚每月一号对应的是周几。当月天数已知,上月残余天数,我们可以用当月号是周几来推断出来,下月残余天数,正好用当月天数上月残余。 最近在做微信小程序项目,其中涉及到日历。一直以来,遇到日历,就是网上随便找个插件,这次心血来潮,想着自己去实现一下。这次不是封装功能强大,健硕完美的组件,只是记录一下,主体思路。更多功能还得根据项目需要,自己去挖...

    import. 评论0 收藏0
  • 前端基础入门

    摘要:手把手教你做个人火的时候,随便一个都能赚的盆满钵满,但是,个人没有服务端,没有美工,似乎就不能开发了,真的是这样的吗秘密花园经典的中文手册。涵盖前端知识体系知识结构图书推荐以及入门视频教程,全的简直不要不要的了。 JavaScript 实现点击按钮复制指定区域文本 html5 的 webAPI 接口可以很轻松的使用短短的几行代码就实现点击按钮复制区域文本的功能,不需要依赖 flash。...

    shinezejian 评论0 收藏0
  • 前端空间 - 收藏集 - 掘金

    摘要:封装手写的方笔记使用检测文件前端掘金副标题可以做什么以及使用中会遇到的坑。目的是帮助人们用纯中文指南实现复选框中多选功能前端掘金作者缉熙简介是推出的一个天挑战。 深入理解 JavaScript Errors 和 Stack Traces - 前端 - 掘金译者注:本文作者是著名 JavaScript BDD 测试框架 Chai.js 源码贡献者之一,Chai.js 中会遇到很多异常处理...

    you_De 评论0 收藏0
  • 前端空间 - 收藏集 - 掘金

    摘要:封装手写的方笔记使用检测文件前端掘金副标题可以做什么以及使用中会遇到的坑。目的是帮助人们用纯中文指南实现复选框中多选功能前端掘金作者缉熙简介是推出的一个天挑战。 深入理解 JavaScript Errors 和 Stack Traces - 前端 - 掘金译者注:本文作者是著名 JavaScript BDD 测试框架 Chai.js 源码贡献者之一,Chai.js 中会遇到很多异常处理...

    lwx12525 评论0 收藏0
  • 信小程序资源汇总

    awesome-github-wechat-weapp 是由OpenDigg整理并维护的微信小程序开源项目库集合。我们会定期同步上的项目到这里,也欢迎各位 UI组件开发框架实用库开发工具服务端项目实例Demo UI组件 weui-wxss ★1873 - 同微信原生视觉体验一致的基础样式库zanui-weapp ★794 - 好用易扩展的小程序 UI 库wx-charts ★449 - 微信小程...

    Olivia 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<