zoukankan      html  css  js  c++  java
  • 前端笔记之React(四)生命周期&Virtual DOM和Diff算法&日历组件开发

    一、React生命周期

    一个组件从出生到消亡,在各个阶段React提供给我们调用的接口,就是生命周期。

    生命周期这个东西,必须有项目,才知道他们干嘛的。


    1.1 Mouting阶段【装载过程

    这个阶段在组件上树的时候发生,依次是:

    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组件:  

    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改变的时候触发,依次是:

    componentWillReceiveProps(nextProps)

    当收到新的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

    二、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.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>
        }
    }

     

  • 相关阅读:
    hive与hbase整合
    待重写
    hive DML
    【知识强化】第六章 总线 6.1 总线概述
    【知识强化】第五章 中央处理器 5.1 CPU的功能和基本结构
    【知识强化】第四章 指令系统 4.3 CISC和RISC的基本概念
    【知识强化】第四章 指令系统 4.2 指令寻址方式
    【知识强化】第四章 指令系统 4.1 指令格式
    【知识强化】第三章 存储系统 3.6 高速缓冲存储器
    【知识强化】第三章 存储系统 3.5 双口RAM和多模块存储器
  • 原文地址:https://www.cnblogs.com/rope/p/10741113.html
Copyright © 2011-2022 走看看