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