摘要:你也可以從其他星期開始,不過會對下面的日期顯示有影響,因?yàn)槊總€月的第一天是周幾決定第一天顯示在第幾個格子里。首先要根據(jù)年月的第一天獲得,根據(jù)這個獲取周幾。
準(zhǔn)備工作
提前需要準(zhǔn)備好react腳手架開發(fā)環(huán)境,由于react已經(jīng)不支持在頁面內(nèi)部通過jsx.transform來轉(zhuǎn)義,我們就自己大了個簡易的開發(fā)環(huán)境
創(chuàng)建一個文件夾,命名為react-canlendar
cd ./react-canlendar
運(yùn)行
npm init
一路enter我們得到一個package.json的文件
安裝幾個我們需要的腳手架依賴包
npm install awesome-typescript-loader typescript webpack webpack-cli -D
安裝幾個我們需要的類庫
npm install @types/react react react-dom --save
基礎(chǔ)類庫安裝完畢,開始構(gòu)建webpack配置
新建一個目錄config,config下面新增一個文件,名字叫做webpack.js
var path = require("path") module.exports = { entry: { main: path.resolve(__dirname, "../src/index.tsx") }, output: { filename: "[name].js" }, resolve: { extensions: [".ts", ".tsx", ".js", ".json"] }, module: { rules: [ {test: /.tsx?$/, use: ["awesome-typescript-loader"]} ] } }
還需要創(chuàng)建一個index.html文件,這是我們的入口文件
Document
以上環(huán)境只是一個極簡單的環(huán)境,真實(shí)環(huán)境要比這個復(fù)雜的多。
好了,言歸正傳,我們還是聚焦到日歷組件的開發(fā)中來吧
創(chuàng)建一個src文件夾,內(nèi)部創(chuàng)建一個index.tsx文件。
這個入口文件很簡單就是一個掛載
import * as React from "react" import * as ReactDOM from "react-dom" ReactDOM.render((test), document.getElementById("root"))
ok,打開頁面可以看到頁面正常顯示了test字樣。
我們需要創(chuàng)建Calendar組件了。
創(chuàng)建一個components文件夾,內(nèi)部創(chuàng)建一個Calendar.tsx文件。
import * as React from "react" export default class Calendar extends React.Component { render() { return (日歷) } }
在index.tsx中把Calendar.tsx引入,并使用起來。于是index.tsx變成這個樣子。
import * as React from "react" import * as ReactDOM from "react-dom" import Calendar from "./components/Calendar" ReactDOM.render((), document.getElementById("root"))
可以看到頁面顯示了日歷字樣。
要顯示日歷,首先需要顯示日歷這個大框以及內(nèi)部的一個個小框。實(shí)現(xiàn)這種布局最簡單的布局就是table了
所以我們首先創(chuàng)建的是這種日歷table小框框,以及表頭的星期排列。
import * as React from "react" const WEEK_NAMES = ["日", "一", "二", "三", "四", "五", "六"] const LINES = [1,2,3,4,5,6] export default class Calendar extends React.Component { render() { return () } }
{ WEEK_NAMES.map((week, key) => { return { LINES.map((l, key) => { return{week} }) }{ WEEK_NAMES.map((week, index) => { return }) }{index} }) }
可以看到我們使用了一個星期數(shù)組作為表頭,我們按照慣例是從周日開始的。你也可以從其他星期開始,不過會對下面的日期顯示有影響,因?yàn)槊總€月的第一天是周幾決定第一天顯示在第幾個格子里。
那為什么行數(shù)要6行呢?因?yàn)槲覀兪前凑兆畲笮袛?shù)來確定表格的行數(shù)的,如果一個月有31天,而這個月的第一天剛好是周六。就肯定會顯示6行了。
為了顯示好看,我直接寫好了樣式放置在index.html中了,這個不重要,不講解。
Document
下面就要開始顯示日期了,首先要把當(dāng)前月份的日期顯示出來,我們先在組件的state中定義當(dāng)前組件的狀態(tài)
state = { month: 0, year: 0, currentDate: new Date() }
我們定義一個方法獲取當(dāng)前年月,為什么不需要獲取日,因?yàn)槿諝v都是按月顯示的。獲取日現(xiàn)在看來對我們沒有意義,于是新增一個方法,設(shè)置當(dāng)前組件的年月
setCurrentYearMonth(date) { var month = Calendar.getMonth(date) var year = Calendar.getFullYear(date) this.setState({ month, year }) } static getMonth(date: Date): number{ return date.getMonth() } static getFullYear(date: Date): number{ return date.getFullYear() }
創(chuàng)建兩個靜態(tài)方法獲取年月,為什么是靜態(tài)方法,因?yàn)榕c組件的實(shí)例無關(guān),最好放到靜態(tài)方法上去。
要想繪制一個月還需要知道一個月的天數(shù)吧,才好繪制吧
所以我們創(chuàng)建一個數(shù)組來表示月份的天數(shù)
const MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] // 暫定2月份28天吧
組件上創(chuàng)建一個函數(shù),根據(jù)月份獲取天數(shù),也是靜態(tài)的
static getCurrentMonthDays(month: number): number { return MONTH_DAYS[month] }
下面還有一個重要的事情,就是獲取當(dāng)前月份第一天是周幾,這樣子就可以決定把第一天繪制在哪里了。首先要根據(jù)年月的第一天獲得date,根據(jù)這個date獲取周幾。
static getDateByYearMonth(year: number, month: number, day: number=1): Date { var date = new Date() date.setFullYear(year) date.setMonth(month, day) return date }
這里獲得每個月的第一天是周幾了。
static getWeeksByFirstDay(year: number, month: number): number { var date = Calendar.getDateByYearMonth(year, month) return date.getDay() }
好了,開始在框子插入日期數(shù)字了。因?yàn)槊總€日期都是不一樣的,這個二維數(shù)組可以先計算好,或者通過函數(shù)直接插入到j(luò)sx中間。
static getDayText(line: number, weekIndex: number, weekDay: number, monthDays: number): any {
var number = line * 7 + weekIndex - weekDay + 1
if ( number <= 0 || number > monthDays ) {
return
}
return number
}
看一下這個函數(shù)需要幾個參數(shù)哈,第一個行數(shù),第二個列數(shù)(周幾),本月第一天是周幾,本月天數(shù)。line * 7 + weekIndex表示當(dāng)前格子本來是幾,減去本月第一天星期數(shù)字。為什么+1,因?yàn)樗饕菑?開始的,而天數(shù)則是從1開始。那么<0 || >本月最大天數(shù)的則過濾掉,返回一個空span,只是為了撐開td。其他則直接返回數(shù)字。
import * as React from "react" const WEEK_NAMES = ["日", "一", "二", "三", "四", "五", "六"] const LINES = [1,2,3,4,5,6] const MONTH_DAYS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] export default class Calendar extends React.Component { state = { month: 0, year: 0, currentDate: new Date() } componentWillMount() { this.setCurrentYearMonth(this.state.currentDate) } setCurrentYearMonth(date) { var month = Calendar.getMonth(date) var year = Calendar.getFullYear(date) this.setState({ month, year }) } static getMonth(date: Date): number{ return date.getMonth() } static getFullYear(date: Date): number{ return date.getFullYear() } static getCurrentMonthDays(month: number): number { return MONTH_DAYS[month] } static getWeeksByFirstDay(year: number, month: number): number { var date = Calendar.getDateByYearMonth(year, month) return date.getDay() } static getDayText(line: number, weekIndex: number, weekDay: number, monthDays: number): any { var number = line * 7 + weekIndex - weekDay + 1 if ( number <= 0 || number > monthDays ) { return } return number } static formatNumber(num: number): string { var _num = num + 1 return _num < 10 ? `0${_num}` : `${_num}` } static getDateByYearMonth(year: number, month: number, day: number=1): Date { var date = new Date() date.setFullYear(year) date.setMonth(month, day) return date } checkToday(line: number, weekIndex: number, weekDay: number, monthDays: number): Boolean { var { year, month } = this.state var day = Calendar.getDayText(line, weekIndex, weekDay, monthDays) var date = new Date() var todayYear = date.getFullYear() var todayMonth = date.getMonth() var todayDay = date.getDate() return year === todayYear && month === todayMonth && day === todayDay } monthChange(monthChanged: number) { var { month, year } = this.state var monthAfter = month + monthChanged var date = Calendar.getDateByYearMonth(year, monthAfter) this.setCurrentYearMonth(date) } render() { var { year, month } = this.state console.log(this.state) var monthDays = Calendar.getCurrentMonthDays(month) var weekDay = Calendar.getWeeksByFirstDay(year, month) return ({this.state.month}) } }
< {year} - {Calendar.formatNumber(month)} >{ WEEK_NAMES.map((week, key) => { return { LINES.map((l, key) => { return{week} }) }{ WEEK_NAMES.map((week, index) => { return }) }{Calendar.getDayText(key, index, weekDay, monthDays)} }) }
可以看到最終的代碼多了一些東西,因?yàn)槲壹恿嗽路莸那袚Q。
還記的上文我們把二月份天數(shù)寫28天嘛?要不你們自己改改,判斷一下閏年。
創(chuàng)建了一個程序員交流微信群,大家進(jìn)群交流IT技術(shù)
如果已過期,可以添加博主微信號15706211347,拉你進(jìn)群
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/113881.html
摘要:你也可以從其他星期開始,不過會對下面的日期顯示有影響,因?yàn)槊總€月的第一天是周幾決定第一天顯示在第幾個格子里。首先要根據(jù)年月的第一天獲得,根據(jù)這個獲取周幾。 準(zhǔn)備工作 提前需要準(zhǔn)備好react腳手架開發(fā)環(huán)境,由于react已經(jīng)不支持在頁面內(nèi)部通過jsx.transform來轉(zhuǎn)義,我們就自己大了個簡易的開發(fā)環(huán)境 創(chuàng)建一個文件夾,命名為react-canlendar cd ./react-c...
摘要:是狀態(tài)容器,提供可預(yù)測化的狀態(tài)管理。一般我們會使用一個常量來表示對應(yīng)的值。作為純函數(shù),內(nèi)部不建議使用任何有副作用的操作,比如操作外部的變量,任何導(dǎo)致相同輸入但輸出卻不一致的操作。結(jié)合,其他類庫,開發(fā)步驟莫不如此。 Redux 是 JavaScript 狀態(tài)容器, 提供可預(yù)測化的狀態(tài)管理。 那什么是可以預(yù)測化,我的理解就是根據(jù)一個固定的輸入,必然會得到一個固定的結(jié)果。 redux是專門為...
學(xué)習(xí)的過程中收藏了這些優(yōu)秀教程和的項目,希望對你有幫助。 github地址, 有不錯的就更新 官方文檔 中文指南 初級教程 webpack-howto 作者:Pete Hunt Webpack 入門指迷 作者:題葉 webpack-demos 作者:ruanyf 一小時包教會 —— webpack 入門指南 作者:VaJoy Larn webpack 入門及實(shí)踐 作者:...
摘要:毫無疑問,設(shè)計模式于己于他人于系統(tǒng)都是多贏的設(shè)計模式使代碼編寫真正工程化設(shè)計模小書前端掘金這是一本關(guān)于的小書。 JavaScript 常見設(shè)計模式解析 - 掘金設(shè)計模式(Design pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、代碼設(shè)計經(jīng)驗(yàn)的總結(jié)。使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。毫無疑問,設(shè)計模式于己于他人于系統(tǒng)都是多贏的;設(shè)計...
閱讀 523·2021-10-09 09:44
閱讀 2108·2021-09-02 15:41
閱讀 3561·2019-08-30 15:53
閱讀 1840·2019-08-30 15:44
閱讀 1295·2019-08-30 13:10
閱讀 1202·2019-08-30 11:25
閱讀 1481·2019-08-30 10:51
閱讀 3372·2019-08-30 10:49