一个基本日历渲染组件

需要一个基本的日历,不需要太多功能,遂简单封装了一个。可以用rollup打个包,便于以后使用。

  1. 主体部分
import {
  formatDate, getMonthDay, chunk,
} from './utils';
import { weekText, monthText } from './text';


export default class Calendar {
  constructor(id, option) {
    // todo 参数校验
    const currentDate = new Date();
    this.id = id; // 渲染到 id
    this.option = Object.assign({}, {
      year: currentDate.getFullYear(), //年
      month: currentDate.getMonth() + 1, //月
      weekText, // 星期名数组
      monthText, //月名数组
      tableName: 'calendar--date_table', //渲染的class
    }, option);
    this.renderYear = this.option.year;
    this.renderMonth = this.option.month;
    this.render();
  }

  next() { //渲染下个月
    if (this.renderMonth + 1 > 12) {
      this.renderMonth = 1;
      this.renderYear += 1;
    } else {
      this.renderMonth += 1;
    }
    this.render();
  }

  pre() { //渲染上个月
    if (this.renderMonth - 1 < 1) {
      this.renderMonth = 12;
      this.renderYear -= 1;
    } else {
      this.renderMonth -= 1;
    }
    this.render();
  }

  getMonthDayArray(year, month) {
    const arr = getMonthDay(year, month).map(v => ({
      date: v,
      formatDate: formatDate(v, 'd', this.monthText, this.weekText),
      week: v.getDay(),
    }));
    const a = arr.map(v => v.formatDate);
    return new Array(arr[0].week).concat(a).concat(new Array((6 - arr[arr.length - 1].week) % 6));
  }

  render() {
    const wArry = this.getMonthDayArray(this.renderYear, this.renderMonth);
    const str = (() => chunk(wArry, 7).reduce((preV, curV) => `${preV}<tr><td>${curV.join('</td><td>')}</td></tr>`, ''))();
    const html = `
    <table class="${this.option.tableName}">
      <thead>
        <tr>
          ${this.option.weekText.map(v => `<td>${v}</td>`).join('')}
        </tr>
      </thead>
      <tbody>
        ${str}
      </tbody>
    </table>
    `;
    document.getElementById(this.id).innerHTML = html;
  }
}
  1. 公用的配置
export const weekText = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
export const monthText = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
  1. 工具函数
import { weekText, monthText } from './text';


const firstDay = (y, m) => new Date(y, m - 1, 1);  //这两个写法比较简洁,记录
const lastDay = (y, m) => new Date(y, m, 0);
const pad = (n, width, z) => {
  const pn = `${n}`;
  return pn.length >= width ? pn : new Array(width - pn.length + 1).join(z || '0') + pn;
};


export const chunk = (arr, size) => Array.from({ length: Math.ceil(arr.length / size) }, (v, i) => arr.slice(i * size, i * size + size));

export const getMonthDay = (y, m) => {
  const f = firstDay(y, m);
  const l = lastDay(y, m);
  let i = f;
  const result = [];
  const d = 24 * 3600 * 1000;
  while (i <= l * 1) {
    result.push(i);
    i = new Date(i.getTime() + d);
  }
  return result;
};

export const formatDate = (dt, format) => {
  let f = format;
  f = f.replace('ss', pad(dt.getSeconds(), 2));
  f = f.replace('s', dt.getSeconds());
  f = f.replace('dd', pad(dt.getDate(), 2));
  f = f.replace('d', dt.getDate());
  f = f.replace('mm', pad(dt.getMinutes(), 2));
  f = f.replace('m', dt.getMinutes());
  f = f.replace('MMMM', monthText[dt.getMonth()]);
  f = f.replace('MMM', monthText[dt.getMonth()].substring(0, 3));
  f = f.replace('MM', pad(dt.getMonth() + 1, 2));
  f = f.replace(/M(?![ao])/, dt.getMonth() + 1);
  f = f.replace('DD', weekText[dt.getDay()]);
  f = f.replace(/D(?!e)/, weekText[dt.getDay()].substring(0, 3));
  f = f.replace('yyyy', dt.getFullYear());
  f = f.replace('YYYY', dt.getFullYear());
  f = f.replace('yy', (`${dt.getFullYear()}`).substring(2));
  f = f.replace('YY', (`${dt.getFullYear()}`).substring(2));
  f = f.replace('HH', pad(dt.getHours(), 2));
  f = f.replace('H', dt.getHours());
  return f;
};
  1. 使用
<button id="pre">pre</button>
<button id="next">next</button>
<h1 id="renderYM"></h1>
<div id="date"></div>
import Calendar from '@/public/calender';

const calendar = new Calendar('date', {
  year: 2019,
  month: 2,
  weekText: ['周日', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
  tableName: 't',
});
const eRenderYM = document.getElementById('renderYM');
const showRenderYM = () => {
  eRenderYM.innerHTML = `${calendar.renderYear}--${calendar.renderMonth}`;
};
showRenderYM();
document.getElementById('next').addEventListener('click', () => {
  calendar.next();
  showRenderYM();
}, false);
document.getElementById('pre').addEventListener('click', () => {
  calendar.pre();
  showRenderYM();
}, false);

转载于:https://my.oschina.net/dtdths/blog/3033137

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值