前端筆記之React(四)生命週期&Virtual DOM和Diff算法&日曆組件開發

1、React生命週期

一個組件從出生到消亡,在各個階段React提供給咱們調用的接口,就是生命週期。javascript

生命週期這個東西,必須有項目,才知道他們幹嗎的。css


1.1 Mouting階段【裝載過程

這個階段在組件上樹的時候發生,依次是:html

constructor(props)     構造函數        做用:初始化state值,此時可訪問props、發Ajax請求
componentWillMount()     組件將要上樹    做用:經常使用於根組件中的引用程序配置,不能作任何涉及DOM的事情完成一些計算工做
render()                渲染組件        做用:建立虛擬DOM,組建的UI樣式
componentDidMount()    組件已經上樹    做用:啓動AJAX調用,加載組件的數據,還能用ref獲得DOM,添加事件監聽

 

App.js前端

import React from "react";
import Child from "./Child.js";
export default class App extends React.Component{
    constructor(){
        super();
        this.state = {
            a:100,
            isShow:true
        }
    }
    render(){
        return <div>
            <button onClick={()=>{this.setState({a:this.state.a+1})}}>改變a值</button>
            <button onClick={()=>{this.setState({isShow:!this.state.isShow})}}>
顯示/隱藏組件
</button>
            { this.state.isShow ? <Child a={this.state.a}></Child> : null }
        </div>
    }
};

 

Child組件:  java

import React from 'react';
export default class Child extends React.Component {
    constructor(){
        super();
        console.log("我是constructor構造函數");
        this.state = {
            m : 200 }
    } //組件將要上樹
 componentWillMount(){
        console.log("我是componentWillMount");
    } //組件已經上樹
 componentDidMount(){
        console.log("我是componentDidMount");
    }

    render(){
        console.log("我是render");  
        return (
            <div>
                <button onClick={()=>{this.setState({m:this.state.m+1})}}>改變m值</button>
                子組件的m值:{this.state.m},
                子組件接收a值:{this.props.a}
            </div>
        );
    }
}

 


1.2 Updating階段【更新過程

當組件的props改變或state改變的時候觸發,依次是:react

componentWillReceiveProps(nextProps)jquery

當收到新的props的時候觸發算法

 

shouldComponentUpdate(nextProps,nextState)數組

【門神函數】當組件stateprops改變時觸發,這個函數須要return true或者false,表示是否繼續進Updating階段。如return false,視圖將再也不更新,大體是爲了增長效率。緩存

 

componentWillUpdate(nextProps, nextState)

當組件stateprops改變時觸發,用來在update的時候進行一些準備。

 

render()渲染方法,建立虛擬DOM

 

componentDidUpdate(prevProps, prevState)

當組件stateprops改變時觸發,用來進行一些更新的驗證。組件更新完成後調用,此時能夠獲取最新的DOM節點,用來驗證信息的。

 

Updating階段中,絕對不容許改變stateprops,不然會死循環。


 

1.3 unmounting階段【卸載過程】

就一個函數:componentWillUnmount()組件將要下樹。

完整的Child.js子組件:

import React from 'react';
export default class Child extends React.Component {
    constructor() {
        super();
        console.log("我是constructor構造函數")
        this.state = {
            m:200
        }
    }
    //組件將要上樹
    componentWillMount(){
        console.log("我是componentWillMount將要上樹")
    }
    //組件已經上樹
    componentDidMount(){
        console.log("我是componentDidMount已經上樹")
    }

//************Updataing階段【更新階段】************** */
// 當組件的props或state改變時觸發
componentWillReceiveProps(nextProps){
    console.log("更階段的:componentWillReceiveProps", nextProps)
}
shouldComponentUpdate(nextProps, nextState) {
    console.log("更階段的:shouldComponentUpdate", nextProps, nextState)
    return true;
}
componentWillUpdate(nextProps, nextState){
    console.log("更階段的:componentWillUpdate", nextProps, nextState)
}
componentDidUpdate(prevProps, prevState){
    console.log("更階段的:componentDidUpdate", prevProps, prevState)
}

//組件下樹
    componentWillUnmount(){
        console.log("componentWillUnmount組件下樹了");
}

    render(){
        console.log("我是render")
        return <div>
            <button onClick={()=>{ this.setState({m: this.state.m + 1 })}}>改變m值</button>
            <h2>子組件的m值:{this.state.m}</h2>
            <h2>子組件接收父組件a值:{this.props.a}</h2>
        </div>
    }
}
示例代碼

 

上樹階段:
    constructor
    componentWillMount
    render
    componentDidMount
更新階段:
    componentWillReceiveProps
    shouldComponentUpdate
    componentWillUpdate
    render
    componentDidUpdate
下樹階段
    componentWillUnmount

2、Virtual DOMDiff算法(理論知識)

React會在內存中存儲一份DOM的鏡像,當有render發生的時候,此時會在內存中用Diff算法進行最小差別比較,實現最小的更新。

Virtual DOMReactVue中的一個很重要的概念,在平常開發中,前端工程師們須要將後臺的數據呈現到界面中,同時要能對用戶的操做提供反饋,做用到UI上…… 這些都離不開DOM操做。可是咱們知道,頻繁的DOM操做會形成極大的資源浪費,也一般是性能瓶頸的緣由。因而ReactVue引入了Virtual DOMVirtual DOM的核心就是計算比較改變先後的DOM區別,而後用最少的DOM操做語句對DOM進行操做

 

如今須要將下圖左邊的DOM結構替換成右邊的結構,這種情景在實戰項目中是常常會遇到的。可是若是直接操做DOM的話,進行移除的話可能就是四次刪除,五次插入,這種消耗是很大的可是使用Virtual DOM,那就是比較兩個結構的差別,發現僅僅改變了四次內容,一次插入這種消耗就小不少,無非加上一個比較的時間。

 

React告訴咱們的是在內存中維護一顆和頁面同樣的DOM樹,這顆DOM樹不是真正渲染在html中的,而是放在內存中的,所以修改它將會特別的快,而且資源消耗也少不少,當咱們render一個頁面的時候首先先將咱們最新的DOM去和內存中的這棵虛擬DOM樹去作對比(髒檢查),而後對比出差別點,而後再用這棵虛擬DOM差別的部分去替換真正DOM樹中的一部分。

 

這就是所謂的 Virtual DOM 算法。包括幾個步驟:

  JavaScript 對象結構表示 DOM 樹的結構;而後用這個樹構建一個真正的 DOM 樹,插到文檔當中。

 當狀態變動的時候,從新構造一棵新的對象樹。而後用新的樹和舊的樹進行比較,記錄兩棵樹差別。

 2所記錄的差別應用到步驟1所構建的真正的DOM樹上,視圖就更新了。

 

Virtual DOM 本質上就是在 JS DOM 之間作了一個緩存。這個概念就和咱們當初學操做系統同樣,能夠類比 CPU 和硬盤,既然硬盤這麼慢,咱們就在它們之間加個緩存:既然 DOM 這麼慢,咱們就在它們 JS DOM 之間加個緩存。CPUJS)只操做內存(Virtual DOM),最後的時候再把變動寫入硬盤(DOM)。

App.js

import React from "react";
export default class App extends React.Component {
    constructor() {
        super();
        this.state = {
            a : 100
        }
    }
    componentDidMount(){
$(this.refs.list).find("li").css("position","relative").animate({"left":500},5000)
    }
    render(){
        console.log("我是render函數")
        return <div>
            <button onClick={()=>{this.setState({a : this.state.a + 1})}}>按我</button>
            <ul ref="list">
                <li>A</li>
                <li>B</li>
                <li>{this.state.a}</li>
                <li>D</li>
            </ul>
        </div>
    }
}

當某一個組件狀態、屬性被更改時,它的子組件、孫組件都會被從新渲染,Virtual DOM也將會計算這些組件的DOM更新。

 


3、日曆組件

3.1業務

日選擇視圖

年選擇視圖

月選擇視圖

 

 

 

 

 

 

 


3.2劃分組件

組件劃分就是根據第一直觀印象便可,按結構、功能獨立進行劃分。

最大組件Canlendar,裏面有數據yearmonthdate

點擊一個按鈕,能夠顯示彈出層,彈出層的組件名:Canlendar_menu

下轄五個組件,五個組件都兄弟:

ChooserDate

 

 

ChooserYear

 

 

ChooserMonth

 

 

PickerDate

 

 

PickerYear

 

 

 

全部的組件不須要對兄弟組件負責,只須要對最大組件的數據負責。

 

【先實現日曆視圖】

index.html

<html>
<head>
    <title>日曆組件</title>
    <link rel="stylesheet" href="css/style.css" />
</head>
<body>
    <div id="app"></div>
    <script type="text/javascript" src="lib/jquery-2.2.4.min.js"></script>
    <script type="text/javascript" src="dist/bundle.js"></script>
</body>
</html>
示例代碼

建立app/components/canlendar/index.js文件,這是最大的組件。

import React from "react";
export default class Canlendar extends React.Component {
    constructor() {
        super();
    }
    render() {
        return <div>
            我是Canlendar組件
        </div>
    }
}

 

app/App.js引入canlendar最大組件

import React from "react";
import Canlendar from "./components/canlendar";
export default class App extends React.Component {
    constructor() {
        super();
     
    }
    render(){
        return <div>
            <div>
                出生日期:<Canlendar></Canlendar>
            </div>
        </div>
    }
}

 

開始寫app/components/canlendar/index.js

import React from "react";
import CanlendarMenu from "./CanlendarMenu.js";
export default class Canlendar extends React.Component {
    constructor() {
        super();
        this.state = {
            year : 2018 ,
            month : 8 ,
            date : 8,
            isShowMenu : false }
    } 
    render() {
        return <div className="canlendar">
            <div className="inputBox">
                {this.state.year}{this.state.month}{this.state.date}</div>
            {
                this.state.isShowMenu 
                ?
                <CanlendarMenu
                    year={this.state.year}
                    month={this.state.month}
                    date={this.state.date}
                ></CanlendarMenu>
                :
                null
            }
        </div>
    }
}

css樣式:

*{margin:0;padding:0;}
.canlendar{position: relative;}
.canlendar .inputBox{
    width: 150px;height: 20px;border: 1px solid #BDBDBD;
    border-radius:2px;position:relative;font-size:13px;
    padding:0 10px;color:#424242;line-height: 20px;
}
.canlendar .inputBox::before{
    content:"";position: absolute;right:0;top:0;
    width:20px;height:20px;background: #F5F5F5;
}
示例代碼

 

開始寫app/components/canlendar/CanlendarMenu.js彈出層

import React from "react";
import PickerDate from "./PickerDate.js";
import ChooserDate from "./ChooserDate.js";
export default class CanlendarMenu extends React.Component {
    constructor() {
        super();
    }
render() {
    //解構獲得年、月、日
    const {year, month, date} = this.props;
        return <div className="canlendar_menu">
            <PickerDate year={year} month={month}></PickerDate>
            <ChooserDate year={year} month={month} date={date}></ChooserDate>
        </div>
    }
}

css樣式:

.canlendar .canlendar_menu{
    position: absolute;top: 26px;left:0;z-index: 999;
    width:360px; height:260px;
    border: 1px solid #BDBDBD;
    box-shadow: 0px 0px 8px #00000036;
    border-radius: 5px;background:white;
}
示例代碼

 

app/components/canlendar/PickerDate.js

import React from "react";
export default class PickerDate extends React.Component {
    constructor() {
        super();
    }
    render() {
       const {year, month} = this.props;
        return <div className="picker">
            <div className="left">
                <a className="btn" href="###">上1月</a>
            </div>
            <div className="center">
                <a href="###">{year}</a>年
                <a href="###">{month}</a>月
            </div>
            <div className="right">
                <a className="btn" href="###">下1月 </a>
            </div>
        </div>
    }
}

css樣式:

.canlendar .picker{padding-top:10px;overflow: hidden;margin-bottom: 13px;}
.canlendar .picker .left{float: left;width:33.33%;text-align: center;}
.canlendar .picker .right{float:left;width:33.33%;text-align: center;}
.canlendar .picker .center{
    float: left;width:33.33%;text-align: center;font-size: 18px;font-weight: bold;
}
.canlendar .picker .btn{
    padding:4px 10px;background: #2196F3;font-size: 12px;
    border-radius: 4px;text-decoration: none;color: white;
}
.canlendar .chooserDate{color:#333;font-size: 12px;}
.canlendar .chooserDate span{display: block;}
.canlendar .chooserDate table{
    width:100%;text-align:center;line-height: 14px;border-collapse:collapse;
}
.canlendar .chooserDate span.cd{font-size: 10px;}
.canlendar .chooserDate table td{padding-bottom: 2px;cursor: pointer;}
.canlendar .chooserDate table th{line-height: 26px;}
.canlendar .chooserDate table td.gray{color: #c1bcbc;}
.canlendar .chooserDate table td.cur{background-color: #FFCDD2;}
示例代碼

 

 

app/components/canlendar/ChooserDate.js

import React from "react";
export default class ChooserDate extends React.Component {
    constructor() {
        super();
    }
    render() {
        return <div className="chooserDate">
            <table>
                <tbody>
                    <tr>
                        <th>日</th>
                        <th>一</th>
                        <th>二</th>
                        <th>三</th>
                        <th>四</th>
                        <th>五</th>
                        <th>六</th>
                    </tr>
                    <tr>
                        <td>
                            <span>31</span>
                            <span className="cd">初一</span>
                        </td>
                    </tr>
                    tr*6>td*7
                </tbody>
            </table>
        </div>
    }
}
import React from "react";
import { solar2lunar } from "solarlunar";
import classnames from "classnames";
export default class ChooserDate extends React.Component {
    constructor() {
        super();
    }
    //顯示錶格
    showTable(){
        const {year , month , date} = this.props;
        //三要素
        var thisMonth1Day = new Date(year, month - 1 , 1).getDay();
        var thisMonthDateAmount = new Date(year, month, 0).getDate();
        var prevMonthDateAmount = new Date(year, month - 1, 0).getDate();
    
        var arr = [];
        //上個月的尾巴
        while(thisMonth1Day--){
            var d = prevMonthDateAmount--;
            var sl = solarLunar.solar2lunar(year, month - 1, d);
          arr.unshift({ "d" : d,
                "cd": sl.term || sl.dayCn,
          }) } //本月
        var count = 0;
        while (thisMonthDateAmount--){
        count++;
            var d = count;
            var sl = solarLunar.solar2lunar(year, month, d);
       arr.push({ "d": d,
                "cd": sl.term || sl.dayCn,
        });
            
       } //下月開頭
        var nextCount = 0;
        while(arr.length != 42){
        nextCount++;
            var d = nextCount; var sl = solarLunar.solar2lunar(year, month + 1, d);
            arr.push({
                "d": d, "cd": sl.term || sl.dayCn,
            });
        }
    //表格上樹顯示
        var domArr = [];
        for(var i = 0;  i < arr.length / 7; i++){
            domArr.push(
                <tr key={i}>
                    {
                        // 數組會自動展開
                        arr.slice(i * 7, i * 7 + 7).map((item, index)=>{
                            return <td key={index}>
                                <span>{item.d}</span>
                                <span className="cd">{item.cd}</span>
                            </td>
 })
                    }
                </tr>
 )
        } return domArr;
    }

    render() {
        return <div className="chooserDate">
            <table>
                <tbody>
                    <tr>
                        <th>日</th>
                        <th>一</th>
                        <th>二</th>
                        <th>三</th>
                        <th>四</th>
                        <th>五</th>
                        <th>六</th>
                    </tr>
                    {this.showTable()}
                </tbody>
            </table>
        </div>
    }
}

 

app/components/canlendar/index.js實現切換上月、下月

import React from "react";
import CanlendarMenu from "./CanlendarMenu.js";
export default class Canlendar extends React.Component {
    constructor() {
        super();
        this.state = {
            year : 2018 ,
            month : 8 ,
            date : 8,
            isShowMenu : false
        }
    } 
  setShowMenu(isShowMenu){ this.setState({isShowMenu});
    }
    setYear(year){
        this.setState({ year });
    }
    setMonth(month){
        this.setState({ month });
    }
    setDate(date){
        this.setState({date}); }
    render() {
        return <div className="canlendar">
            <div className="inputBox" onClick={()=>{this.setState({"isShowMenu" : true})}}>
                {this.state.year}年{this.state.month}月{this.state.date}日
            </div>
            {
                this.state.isShowMenu 
                ?
                <CanlendarMenu
                    year={this.state.year}
                    month={this.state.month}
                    date={this.state.date}
                    setYear={this.setYear.bind(this)}
                    setMonth={this.setMonth.bind(this)}
                    setDate={this.setDate.bind(this)}
                    setShowMenu={this.setShowMenu.bind(this)}
                ></CanlendarMenu>
                :
                null
            }   
        </div>
    }
}

 

而後經過app/components/canlendar/CanlendarMenu.js繼續往下傳

import React from "react";
import PickerDate from "./PickerDate.js";
import ChooserDate from "./ChooserDate.js";
export default class CanlendarMenu extends React.Component {
    constructor() {
        super();
    }
render() {
    //解構獲得年、月、日
    const {year, month, date, setYear, setMonth, setDate, setShowMenu} = this.props;
        return <div className="canlendar_menu">
          <PickerDate setYear={setYear} setMonth={setMonth}></PickerDate>
          <ChooserDate setYear={setYear} setMonth={setMonth} setDate={setDate}></ChooserDate>
        </div>
    }
}

 

canlender/PickerDate.js

import React from "react";
export default class PickerDate extends React.Component {
    constructor() {
        super();
    }
    //下一月
    nextMonth(){
        //若是不是12月,此時月份加1 
        if(this.props.month != 12){
            this.props.setMonth(this.props.month + 1);
        }else{
            //若是是12月,此時月份變爲1,年加1
           this.props.setMonth(1); this.props.setYear(this.props.year + 1);
        }   
    }
    //上一月
    prevMonth(){
        if(this.props.month != 1) {
            this.props.setMonth(this.props.month - 1);
        }else{
            this.props.setMonth(12); this.props.setYear(this.props.year - 1); } }
    render() {
        const {year, month} = this.props;
        return <div className="picker">
            <div className="left">
                <a className="btn" href="###" onClick={()=>{this.prevMonth()}}>上1月</a>
            </div>
            <div className="center">
                <a href="###">{year}</a>年
                <a href="###">{month}</a>月
            </div>
            <div className="right">
                <a className="btn" href="###" onClick={()=>{this.nextMonth()}}>下1月</a>
            </div>
        </div>
    }
}

 

完善app/components/canlendar/ChooserDate.js

添加類名,點擊單元格切換

import React from "react";
import { solar2lunar } from "solarlunar";
import classnames from "classnames";
export default class ChooserDate extends React.Component {
    constructor() {
        super();
    }
    
    //點擊某一個小格格改變年月日
    clickTd(d, isPrevMonth, isNextMonth){
        this.props.setDate(d);    //設置日子
        this.props.setShowMenu(false);    //關閉菜單
        if(isPrevMonth){
            var dd = new Date(this.props.year, this.props.month - 2, d); //月份要重算 this.props.setMonth(dd.getMonth() + 1); //改變月份 this.props.setYear(dd.getFullYear()); //改變年
        }else if(isNextMonth){
            var dd = new Date(this.props.year, this.props.month, d); //月份要重算 this.props.setMonth(dd.getMonth() + 1); //改變月份 this.props.setYear(dd.getFullYear()); //改變年
        }
    }

    //顯示錶格
    showTable(){
        const {year , month , date} = this.props;
        //三要素
           .......

        var arr = [];
        //上個月的尾巴
        var count = thismonth1day;
        while(count--){
            var d = prevmonthdateamount - count;
            var sl = solar2lunar(year, month - 1, d);
            arr.push({
                "d" : d,
                "cd": sl.term || sl.dayCn,
                "gray" : true ,
                "cur" : false ,
                "prevMonth" : true
            })
        }
        //本月
        var count = 1;
        while (count <= thismonthdateamount){
            var d = count;
            var sl = solar2lunar(year, month, d);
            arr.push({
                "d": d,
                "cd": sl.term || sl.dayCn,
                "gray": false ,
                "cur": date == d
            });
            count++;
        }
        //下月開頭
        var count = 1;
        while(arr.length != 35 && arr.length != 42){
            var d = count++;
            var sl = solar2lunar(year, month + 1, d);
            arr.push({
                "d": d,
                "cd": sl.term || sl.dayCn,
                "gray" : true ,
                "cur" : false ,
                'nextMonth' : true
            });
        }

        var domArr = [];
        for(var i = 0 ;  i < arr.length / 7 ; i++){
            domArr.push(
                <tr key={i}>
                    {
                        // 數組會自動展開
                        arr.slice(i * 7, i * 7 + 7).map((item, index) => {
                            return <td 
                                key={index} 
                              className={classnames({"gray":item.gray, "cur":item.cur})}
                                onClick={()=>{this.clickTd(item.d, item.prevMonth, item.nextMonth)}}
                            >
                                <span className="d">{item.d}</span>
                                <span className="cd">{item.cd}</span>
                            </td>
                        })
                    }
                </tr>
            )
        }
        return domArr;
    }
    render() {
        return <div className="chooserDate">
            <table>
                ...   
            </table>
        </div>
    }
}

 

app/components/canlendar/CanlendarMenu.js切換視圖

import React from "react";
import PickerDate from "./PickerDate.js";
import ChooserDate from "./ChooserDate.js";
import ChooserDate from "./ChooserYear.js";
export default class CanlendarMenu extends React.Component {
    constructor() {
        super();
    }
render() {
    //解構獲得年、月、日
    const {year, month, date} = this.props;
        return <div className="canlendar_menu">
            <PickerDate year={year} month={month}></PickerDate>
            {/*<ChooserDate year={year} month={month} date={date}></ChooserDate>*/}
        <ChooserYear year={year} setYear={setYear}></ChooserYear>
        </div>
    }
}

 

app/components/canlendar/ChooserYear.js

import React from "react";
import classnames from "classnames";
export default class chooserYear extends React.Component {
    constructor() {
        super();
    }
    //組件上樹以後
    componentDidMount(){
        var self = this;
        //事件委託,由於td太多了
        $(this.refs.table).on("click","td", function(){
            //獲得你點擊的小格格里面的內容,內容就是年份
            var year = $(this).html(); self.props.setYear(year); //設年 self.props.setView("date"); //回到日視圖
        });
    }
 
    //顯示錶格
    showTable(){
        //算出基數年,好比當前2018年,基數年就是2010年。就是年份減去「零頭」。
        const baseYear = this.props.year - this.props.year % 10;
        var arr = [];
        for(var i = 0; i < 10 ; i++){
            arr.push(
                <tr key={i}>
                    <td>{baseYear + i - 20}</td>
                    <td>{baseYear + i - 10}</td>
                    <td className={classnames({"cur":baseYear + i == this.props.year})}>
              {baseYear + i}
            </td>
                    <td>{baseYear + i + 10}</td>
                    <td>{baseYear + i + 20}</td>
                </tr>
            )
        }
        return arr;
    }
    render() {
        return <div className="chooserYear">
            <table ref="table">
                <tbody>
                    {this.showTable()}
                </tbody>
            </table>
        </div>
    }
}

CSS樣式:

.canlendar .chooserYear table .cur{color:red;font-weight: bold;}
.canlendar .chooserMonth table{
    width:100%;text-align: center;line-height: 40px;
}
.canlendar a{
    color: #2196F3;text-decoration: none;padding: 0 3px;
}
示例代碼

 

canlendar/CanlendarMenu.js

import React from "react";
import PickerDate from "./PickerDate.js";
import PickerYear from "./PickerYear.js";
import ChooserDate from "./ChooserDate.js";
import ChooserYear from "./ChooserYear.js";
import ChooserMonth from "./ChooserMonth.js";
export default class CanlendarMenu extends React.Component {
    constructor() {
        super();
        this.state = {
            view : "date"  //當前的視圖date、month、year
 }
    }
    //設置視圖
    setView(view){
        this.setState({view}); }
    render() {
        //解構獲得年、月、日
        const { year, month, date, setYear, setMonth, setDate, setShowMenu} = this.props;
         
        //定義Chooser組件
        const Chooser = ()=>{
            //根據state的view屬性的值,來決定真實的chooser
            if(this.state.view == "date"){
                return <ChooserDate
                    year={year}
                    month={month}
                    date={date}
                    setYear={setYear}
                    setMonth={setMonth}
                    setDate={setDate}
                    setShowMenu={setShowMenu}
                ></ChooserDate>
            }else if(this.state.view == "year"){
                return <ChooserYear
                    year={year}
                    setYear={setYear}
                    setView={this.setView.bind(this)}
                ></ChooserYear>
            } else if (this.state.view == "month") {
                return <ChooserMonth
                    setMonth={setMonth}
                    setView={this.setView.bind(this)}
                ></ChooserMonth>
            }
        }

        //定義Picker組件
        const Picker = ()=>{
            if(this.state.view == "date"){
                return <PickerDate 
                    year={year} 
                    month={month} 
                    setYear={setYear} 
                    setMonth={setMonth} 
                    setView={this.setView.bind(this)}
                ></PickerDate> 
            }else if(this.state.view == "year"){
                return < PickerYear
                    year={year}
                    setYear={setYear}
                ></PickerYear >
            }else if(this.state.view == "month"){
                return null;
            } } return <div className="canlendar_menu">
            <Picker></Picker>
            <Chooser></Chooser>
        </div>
    }
}

 

canlendar/PickerYear.js

import React from "react";
export default class PickerYear extends React.Component {
    constructor() {
        super();
    }
    render() {
        const {year, setYear} = this.props;
        return <div className="picker">
            <div className="left">
                <a className="btn" href="javascript:;" onClick={()=>{setYear(year-1)}}>
                   上1年
                </a>
            </div>
            <div className="center"> {year}</div>
            <div className="right">
                <a className="btn" href="javascript:;" onClick={()=>{ setYear(year + 1)}}>
                    下1年
                </a>
            </div>
        </div>
    }
}

canlendar/ChooserMonth.js

import React from "react";
import classnames from "classnames";
export default class chooserMonth extends React.Component {
    constructor() {
        super();

    }
    componentDidMount(){
        //事件委託
        var self = this;
        $(this.refs.table).on("click","td", function(){
            self.props.setMonth(parseInt($(this).data("m"))); self.props.setView("date"); })
    }
    render() {
        return <div className="chooserMonth">
            <table ref="table">
                <tbody>
                    <tr>
                        <td data-m="1">1月</td>
                        <td data-m="7">7月</td>
                    </tr>
                    <tr>
                        <td data-m="2">2月</td>
                        <td data-m="8">8月</td>
                    </tr>
                    <tr>
                        <td data-m="3">3月</td>
                        <td data-m="9">9月</td>
                    </tr>
                    <tr>
                        <td data-m="4">4月</td>
                        <td data-m="10">10月</td>
                    </tr>
                    <tr>
                        <td data-m="5">5月</td>
                        <td data-m="11">11月</td>
                    </tr>
                    <tr>
                        <td data-m="6">6月</td>
                        <td data-m="12">12月</td>
                    </tr>
                </tbody>
            </table>
        </div>
    }
}
相關文章
相關標籤/搜索