美文网首页javascript
彻底理解React组件的生命周期(一)

彻底理解React组件的生命周期(一)

作者: 张培跃 | 来源:发表于2018-09-07 23:49 被阅读49次

    React组件的生命周期,主要分为挂载、更新以及移除阶段的生命周期。所谓挂载指的是组件从初始化到渲染到页面的过程。卸载指的是组件生成的DOM元素从页面中删除的过程。更新指的是组件更新的过程。那么在这些过程当中它都经历了些什么呢?

    首先来一段代码:

    ReactDOM.render(
        <Book/>
        document.querySelector("#wrap")
    )
    

    其实以上代码在经过React.js的编译后会变成这个样子:

    ReactDOM.render(
        // <Book/>,
        React.createElement(Book),
        document.querySelector("#wrap")
    )
    

    也就是说将Book传给了React.createElement函数,又将该函数的结果返回给了ReactDOM.rende。最后将组件挂载到了id为wrap的元素中!我们也可以大胆的猜测一下在这个过程中它都做了些什么事:

    // React.createElement 中实例化一个 Book
    const book = new Book(props, children)
    // React.createElement 中调用 book.render 方法渲染组件的内容
    const bookJsxObject = book.render()
    
    // ReactDOM 用渲染后的 JavaScript 对象来来构建真正的 DOM 元素
    const bookDOM = createDOMFromObject(bookJsxObject)
    // ReactDOM 把 DOM 元素塞到页面上
    document.querySelector("#wrap").innerHTML=bookDOM;
    

    以上代码也可以简单理解为:

    // 实例化组件,也就是构造DOM元素
    constructor();
    // 将构造的元素插入到指定的页面元素中
    render();
    

    不过在挂载的过程当中,其实还有两个方法,分别为componentWillMount 和 componentDidMount。

    // 实例化组件,也就是构造DOM元素
    constructor();
    // 当DOM元素载入之前调用
    componentWillMount();
    // 将构造的元素插入到指定的页面元素中
    render();
    // 当DOM元素载入页面之后调用
    componentDidMount();
    

    componentWillMount方法在组件挂载到页面之前调用。而componentDidMount方法是在挂载到页面以后调用。我们也可以将这两个方法放到组件内部:

    class Book extends React.Component{
        constructor(){
            super();
            console.log("执行constructor");
        }
        componentWillMount(){
            console.log("执行componentWillmount");
        }
        componentDidMount(){
            console.log("执行componentDidMount");
        }
        render(){
            console.log("执行render");
            return (
                <div>大家好,我叫张培跃</div>
            )
        }
    }
    ReactDOM.render(
        <Book/>,
        document.querySelector("#wrap")
    )
    

    通过以上示例的输出结果,我们也可以看到方法的执行顺序:

    ->执行constructor
    ->执行componentWillmount
    ->执行render
    ->执行componentDidMount
    
    componentWillmount在render之前,componentDidMount在render之后

    接下来咱们再来思考一个问题,我们既然可以将组件挂载到页面中,自然也可以将组件在页面中进行卸载。而当组件卸载之前会调用组件的componentWillUnmount方法:

    // 实例化组件,也就是构造DOM元素
    constructor();
    // 当DOM元素载入之前调用
    componentWillMount();
    // 将构造的元素插入到指定的页面元素中
    render();
    // 当DOM元素载入页面之后调用
    componentDidMount();
    // 当从页面中卸载时会调用
    componentWillUnmount()
    

    接下来,我们再来定义一个组件,让该组件控制对Book组件的挂载与卸载:

    class My extends React.Component{
        constructor(){
            super();
            this.state={
                isShow:true
            };
            this.changeIsShow=this.changeIsShow.bind(this);
        }
        changeIsShow(){
            this.setState({
                isShow:!this.state.isShow
            })
        }
        render(){
            return (
                <div>
                    <input type="button" value="点我啊"
                               onClick={this.changeIsShow}/>
                    {/*根据isShow来对Book进行挂载与卸载*/}
                    {this.state.isShow?<Book />:null}
                </div>
            )
        }
    }
    ReactDOM.render(
        <My/>,
        document.querySelector("#wrap")
    )
    

    然后在在Book组件中增加componentWillUnmount方法:

    class Book extends React.Component{
        constructor(){
            super();
            console.log("执行constructor");
        }
        componentWillMount(){
            console.log("执行componentWillmount");
        }
        componentDidMount(){
            console.log("执行componentDidMount");
        }
        componentWillUnmount(){
            console.log("执行componentWillUnmount");
        }
        render(){
            console.log("执行render");
            return (
                <div>大家好,我叫张培跃</div>
            )
        }
    }
    

    当点击按钮时控制台会输出最后一行,说明componentWillUnmount方法在被卸载时调用了:

    ->执行constructor
    ->执行componentWillmount
    ->执行render
    ->执行componentDidMount
    

    完整示例代码:

    class Book extends React.Component{
        constructor(){
            super();
            console.log("执行constructor");
        }
        componentWillMount(){
            console.log("执行componentWillmount");
        }
        componentDidMount(){
            console.log("执行componentDidMount");
        }
        componentWillUnmount(){
            console.log("执行componentWillUnmount");
        }
        render(){
            console.log("执行render");
            return (
                <div>大家好,我叫张培跃</div>
            )
        }
    }
    class My extends React.Component{
        constructor(){
            super();
            this.state={
                isShow:true
            };
            this.changeIsShow=this.changeIsShow.bind(this);
        }
        changeIsShow(){
            this.setState({
                isShow:!this.state.isShow
            })
        }
        render(){
            return (
                <div>
                    <input type="button" value="点我啊" 
                              onClick={this.changeIsShow}/>
                    {/*根据isShow来对Book进行挂载与卸载*/}
                    {this.state.isShow?<Book />:null}
                </div>
            )
        }
    }
    ReactDOM.render(
        <My/>,
        document.querySelector("#wrap")
    )
    
    到目前为止,咱们已经见证了组件从出生到死亡的一个过程!接下来我们一起通过一个计数器的实例来了解这些函数的作用!

    现在我们要完成一个倒计时的小应用,如下:


    首先通过constructor进行初始化:

    class AddOne extends React.Component{
        constructor(){
            super();
            //设置初始值
            this.state={
                num:0,
                timer:null
            }
        }
        componentWillMount(){
            // 组件挂载时添加计数器
            this.timer=setInterval(()=>{
                this.setState({
                    num:this.state.num+1
                })
            },1000)
        }
        componentWillUnmount(){
            // 组件卸载时移除计数器
            clearInterval(this.timer);
        }
        render(){
            return (
                <div>
                    <h1>{this.state.num}</h1>
                </div>
            )
        }
    }
    class Start extends React.Component{
        constructor(){
            super();
            this.state={
                isShow:false
            };
            this.changeIsShow=this.changeIsShow.bind(this);
        }
        changeIsShow(){
            this.setState({
                isShow:!this.state.isShow
            })
        }
        render(){
            return (
                <div>
                    <input type="button" value={this.state.isShow?"结束":"开始计时"} onClick={this.changeIsShow}/>
                    {this.state.isShow?<AddOne />:null}
                </div>
            );
        }
    }
    ReactDOM.render(
        <Start/>,
        document.querySelector("#wrap")
    )
    

    小结一下:

    • componentWillMount:在组件调用 render 方法之前调用。
    • componentDidMount:是 DOM 元素已经插入页面后调用。
    • componentWillUnmount:组件对应的 DOM 元素从页面中卸载之前调用。

    未完,等续

    相关文章

      网友评论

        本文标题:彻底理解React组件的生命周期(一)

        本文链接:https://www.haomeiwen.com/subject/hfemwftx.html