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>
        }
    }

     

  • 相关阅读:
    ElementUI中弹窗使用textarea原样显示SpringBoot后台带换行的StringBuilder内容
    Node搭建静态资源服务器时后缀名与响应头映射关系的Json文件
    Nodejs中搭建一个静态Web服务器,通过读取文件获取响应类型
    JS中怎样比较两个时分格式的时间大小
    ElementUI中对el-table的某一列的时间进行格式化
    MongoDb在Windows上的下载安装以及可视化工具的下载与使用
    Express中使用ejs新建项目以及ejs中实现传参、局部视图include、循环列表数据的使用
    FFmpeg-20160506-snapshot-bin
    FFmpeg-20160428-snapshot-bin
    FFmpeg-20160422-snapshot-bin
  • 原文地址:https://www.cnblogs.com/rope/p/10741113.html
Copyright © 2011-2022 走看看