美文网首页
2018-10-13

2018-10-13

作者: 龙波帝国 | 来源:发表于2018-10-13 18:34 被阅读0次


react的生命周期(一)


1.概述

官方简述版:可参考我的另一篇文章:https://www.jianshu.com/p/953ec89995d2

所谓生命周期,就是一个对象从开始生成到最后消亡所经历的状态,理解空间的生命周期,是开发中必须掌握的一个知识点。就像 Android 开发中组件 一样,React Native的组件也有生命周期(Lifecycle)。

React Native组件的生命周期大致上可以划分为实例化阶段、存在阶段和销毁阶段。我们只有在理解组件生命周期的基础上,才能开发出高性能的app。

React Native中组件的生命周期大致可以用以下图表示:

图解: 

第一阶段:是组件第一次绘制阶段,如图中的上面虚线框内,在这里完成了组件的加载和初始化; 

第二阶段:是组件在运行和交互阶段,如图中左下角虚线框,这个阶段组件可以处理用户交互,或者接收事件更新界面; 

第三阶段:是组件卸载消亡的阶段,如图中右下角的虚线框中,这里做一些组件的清理工作

废话不多说,光讲理论可能也不太清楚,我们来看代码,研究一下:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

import React from "react";

import ReactDOM from "react-dom";

class  Parent extends React.Component{

    static defaultProps  = {

        c:88

    }

    constructor(a){

        //a.b=9;// 不可以进行修改;

        super(a);

        // 如果需要在constructor需要获取属性,那么需要在super传进去整个对象

        //console.log(this.props);// undefined

        //console.log(this.props);

        this.state={num:100}

    }

    componentWillMount(){

        // 钩子函数中的this指向当前组件的实例;

        //console.log(this);

        // render执行之前,将要挂载元素之前;

        // 在这个钩子函数中不可以操作DOM;因为当前还没有进行挂载;

        // console.log(this.refs.a);

        // setState 在componentWillMount这个钩子函数中是同步的;

        // 只有将要挂载组件时执行一次,当数据更新时,不再执行;

        this.setState({num:200});

    }

    componentDidMount(){

        // 在render渲染完之后;

        // 当组件渲染完成,执行当前的钩子函数;经常可以在这里操作页面中的DOM元素;

        console.log(this.refs.a);

    }

    add=()=>{

        // 在给元素的绑定事件中,一般写成箭头函数;因为箭头函数中没有this;会指向外层作用域的this;通过this去获取或改变状态;

        this.setState({num:this.state.num+1})

    }

    shouldComponentUpdate(nextProps,nextState){

        console.log("shouldComponentUpdate");

        console.log(nextProps, nextState);

        /*if(nextState.num<210){

            this.setState({num:this.state.num+1})

        }*/

        // nextProps\nextState代表最新状态和最新的属性

        // 返回true,会默认调用render方法;如果返回false,不再调用render;

        //return !(nextState.num%2);

        return 1;

    }

    componentWillUpdate(){

        // 根据shouldComponentUpdate的返回值判断该方法是否执行;并且是在render之前执行的;

        console.log("componentWillUpdate")

    }

    componentDidUpdate(){

        console.log("componentDidUpdate")

    }

    /*componentWillReceiveProps(){

        console.log("componentWillReceiveProps")

    }*/

    render(){

        console.log("render");

        return <div>

            <p ref="a">{this.state.num}</p>

            <Son val={this.state.num}/>

            <button onClick={this.add}>加1</button>

        </div>

    }

}

class Son extends React.Component{

    componentWillReceiveProps(nextProps){

        // nextProps :代表更新之后的属性;

        console.log("componentWillReceiveProps")

    }

    shouldComponentUpdate(nextProps,nextState){

        // 当属性或状态其中一个发生改变,就会触发这个函数;

        console.log("儿子 shouldComponentUpdate");

        console.log(nextProps, nextState);

        return 1;

    }

    componentWillUpdate(){

        // 根据shouldComponentUpdate的返回值判断该方法是否执行;并且是在render之前执行的;

        console.log(" 儿子componentWillUpdate")

    }

    componentDidUpdate(){

        console.log("儿子 componentDidUpdate")

    }

    render(){

            return <div>

                {this.props.val}

            </div>

    }

}

// 生命周期钩子函数的执行顺序:当初始化react实例时,调用的钩子函数;

// defaultProps==>constructor==>componentWillMount==>render==>componentDidMount

// 当数据更新时,执行的钩子函数

// shouldComponentUpdate===>componentWillUpdate==>render==> componentDidUpdate

ReactDOM.render(

<Parent a="1" b="100"/>,

document.querySelector("#root")

);

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2.生命周期分析

2.1实例化阶段分析

钩子函数1:getDefaultProps

该函数用于初始化一些默认的属性,通常会将固定的内容放在这个函数 中进行初始化和赋值;

在组件创建之前,会先调用 getDefaultProps()初始化一些属性,由于组件初始化后,再次使用该组件不会调用getDefaultProps(),所以组件自己不可以自己修改props。

钩子函数2:getInitialState

该函数是用于对组件的一些状态进行初始化;

该函数不同于getDefaultProps,在以后的过程中,可以再次调用。

比如:

this.setState({   

        activePage: activePage,   

currentX: contentOffSetX });

注:一旦调用了this.setState方法,组件一定会调用render方法,对组件进行再次的渲染,不过,如果React框架会自动根据DOM的状态来判断是否需要真正的渲染。

钩子函数3:componentWillMount

这个函数调用时机是在组件创建,并初始化了状态之后,在第一次绘制 render() 之前。这个函数在整个生命周期中只被调用一次。

render是一个组件中必须有的方法,本质上是一个函数,并返回JSX或其他组件来构成DOM,和Android的XML布局类似。作用是通知系统准备加载组件。

钩子函数4:componentDidMount

该方法是在调用了render方法后,通知组件已经加载完成。一般会在这个函数中处理网络请求等加载数据的操作;

2.2.存在期阶段分析

钩子函数5:componentWillReceiveProps

如果组件收到新的属性(props),就会调用 componentWillReceiveProps()对组件的props或state进行了修改。

旧的属性还是可以通过 this.props 来获取,通过调用 this.setState() 来更新你的组件状态,这里调用更新状态是安全的,并不会触发额外的 render() 调用。

钩子函数6:shouldComponentUpdate

当组件接收到新的属性和状态改变的话,都会触发调用 shouldComponentUpdate(…),通过返回false或true来控制是否进行界面的渲染。如果 true 表示需要更新,继续走后面的更新流程。否者,则不更新,直接进入等待状态。

钩子函数7:componentWillUpdate

如果组件状态或者属性改变,并且上面的 shouldComponentUpdate() 返回为 true,就会开始准更新组件,并调用 componentWillUpdate(),组件刷新前调用,有点类似于componentWillMount()。

钩子函数8:componentDidUpdate

调用了 render() 更新完成界面之后,会调用 componentDidUpdate() 来得到通知,其函数原型如下:

void componentDidUpdate(  

        object prevProps,

        object prevState

);

2.3销毁期阶段分析

钩子函数9:componentWillUnmount

当组件要被从界面上移除的时候,就会调用 componentWillUnmount(),该函数可以做一些组件相关的清理工作,例如取消计时器、网络请求等。

总结

补充

什么是DOM Diff算法?

Web界面由DOM树来构成,当其中某一部分发生变化时,其实就是对应的某个DOM节点发生了变化。在React中,构建UI界面的思路是由当前状态决定界面。前后两个状态就对应两套界面,然后由React来比较两个界面的区别,’这就需要对DOM树进行Diff算法分析。

即给定任意两棵树,找到最少的转换步骤。但是标准的的Diff算法复杂度需要O(n^3),这显然无法满足性能要求。要达到每次界面都可以整体刷新界面的目的,势必需要对算法进行优化。这看上去非常有难度,然而Facebook工程师却做到了,他们结合Web界面的特点做出了两个简单的假设,使得Diff算法复杂度直接降低到O(n)两个相同组件产生类似的DOM结构,不同的组件产生不同的DOM结构;对于同一层次的一组子节点,它们可以通过唯一的id进行区分。

---------------------

作者:龙波帝国------------------->打造我的It帝国

欢迎交流,在下扣号:724711690,请备注:前端技术交流

相关文章

网友评论

      本文标题:2018-10-13

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