zoukankan      html  css  js  c++  java
  • react进阶第四讲——生命周期

    类组件生命周期

    当发现fiber tag = 1时,表示遇到类组件。

    /* workloop React 处理类组件的主要功能方法 */
    function updateClassComponent(){
        let shouldUpdate
        const instance = workInProgress.stateNode // stateNode 是 fiber 指向 类组件实例的指针。
         // instance 为组件实例,如果组件实例不存在,证明该类组件没有被挂载过,那么会走初始化流程
         if (instance === null) { 
            // 1. workInProgress 树,当前正在调和的 fiber 树 2. Component 就是项目中的 class 组件3. nextProps 作为组件在一次更新中新的 props 。
            constructClassInstance(workInProgress, Component, nextProps); // 组件实例将在这个方法中被new
            // renderExpirationTime 作为下一次渲染的过期时间。
            mountClassInstance(workInProgress,Component, nextProps,renderExpirationTime );  //初始化挂载组件流程。  
            // shouldUpdate 标识用来证明 组件是否需要更新。
            shouldUpdate = true;
         }else{  
            // 更新组件流程
            shouldUpdate = updateClassInstance(current, workInProgress, Component, nextProps, renderExpirationTime)
         }
         if(shouldUpdate){
             nextChildren = instance.render(); /* 执行render函数 ,得到子节点 */
             // current 树,在初始化更新中,current = null ,在第一次 fiber 调和之后,会将 workInProgress 树赋值给 current 树。
            reconcileChildren(current,workInProgress,nextChildren,renderExpirationTime) /* 继续调和子节点 */
         }
    }
    

    React 的大部分生命周期的执行,都在 mountClassInstance 和updateClassInstance 这两个方法中执行。

    初始化阶段

    function mountClassInstance(workInProgress,ctor,newProps,renderExpirationTime) {
        const instance = workInProgress.stateNode;
        const getDerivedStateFromProps = ctor.getDerivedStateFromProps; /* ctor 就是我们写的类组件,获取类组件的静态方法 */
        if (typeof getDerivedStateFromProps === 'function') {
            const partialState = getDerivedStateFromProps(nextProps, prevState); // 得到将被合并的state 
            const memoizedState = partialState === null || partialState === undefined ? prevState : Object.assign({}, prevState, partialState); // 合并state
            workInProgress.memoizedState = memoizedState;
            instance.state = workInProgress.memoizedState; // 就是我们在组件中 this.state获取的state
        }
        // 当 getDerivedStateFromProps 和 getSnapshotBeforeUpdate 不存在的时候 
        if(typeof ctor.getDerivedStateFromProps !== 'function' &&   typeof instance.getSnapshotBeforeUpdate !== 'function' && typeof instance.componentWillMount === 'function' ) {
            instance.componentWillMount(); 
        }
    }
    

    更新阶段

    /**
    * current: current 树,在初始化更新中,current = null ,在第一次 fiber 调和之后,会将 workInProgress 树赋值给 current 树。
    * workInProgress: 当前正在调和的 fiber 树
    * ctor: 就是我们写的类组件
    **/
    function updateClassInstance(current,workInProgress,ctor,newProps,renderExpirationTime) {
        const instance = workInProgress.stateNode;
        const hasNewLifecycles =  typeof ctor.getDerivedStateFromProps === 'function'
        if(!hasNewLifecycles && typeof instance.componentWillReceiveProps === 'function') {
            if (oldProps !== newProps || oldContext !== nextContext) {     // 浅比较 props 不相等
                instance.componentWillReceiveProps(newProps, nextContext);  // 执行生命周期  
             } 
        }
        let newState = (instance.state = oldState);
        if (typeof getDerivedStateFromProps === 'function')  {
            ctor.getDerivedStateFromProps(nextProps,prevState)  /* 执行生命周期getDerivedStateFromProps  ,逻辑和mounted类似 ,合并state  */
            newState = workInProgress.memoizedState;
        }
        let shouldUpdate = true    
        if(typeof instance.shouldComponentUpdate === 'function' ){
            shouldUpdate = instance.shouldComponentUpdate(newProps,newState,nextContext);
        }
        if(shouldUpdate){
            if (typeof instance.componentWillUpdate === 'function') {
                instance.componentWillUpdate(); /* 执行生命周期 componentWillUpdate  */
            }
        }
        return shouldUpdate
    }
    

    image

    • 初始化阶段:constructor -> getDerivedStateFromProps / componentWillMount -> render -> componentDidMount
    • 更新阶段:componentWillReceiveProps( props 改变) / getDerivedStateFromProp -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate
    • 卸载阶段:componentWillUnMount
    1. constructor:
    • 在类组件创建实例时调用,而且初始化的时候执行一次,所以可以在 constructor 做一些初始化的工作。
    1. getDerivedStateFromProps:
    • 代替 componentWillMount 和 componentWillReceiveProps
    • 组件初始化或者更新时,将 props 映射到 state。
    • 返回一个对象来更新 state,如果返回 null 则不更新任何内容。
    getDerivedStateFromProps(nextProps,prevState)
    

    getDerivedStateFromProps 方法作为类的静态属性方法执行,内部是访问不到 this。

    1. componentWillUpdate 后期版本作废,不要使用
    2. getSnapshotBeforeUpdate
    • 配合componentDidUpdate 一起使用,计算形成一个 snapShot 传递给 componentDidUpdate 。保存一次更新前的信息。
    getSnapshotBeforeUpdate(prevProps,preState) { return xxx}
    

    函数组件生命周期

    1. useEffect
    useEffect(()=>{
        const subscription = props.source.subscribe();
          return () => {
            // 清除订阅
            subscription.unsubscribe();
          };
    },dep)
    
    useEffect(()=>{
        return destory
    },dep)
    
    • useEffect 第一个参数 callback,返回的destory作为下一次callback执行之前调用,用于清除上一次 callback 产生的副作用。在执行下一个 effect 之前,上一个 effect 就已被清除。
    • 第二个参数作为依赖项,是一个数组,可以有多个依赖项,依赖项改变,执行上一次callback 返回的 destory ,和执行新的 effect 第一个参数 callback 。
    • 对于 useEffect 执行, 采用异步调用 ,对于每一个 effect 的 callback, 会被放入任务队列,等到主线程任务完成才执行。所以effect回调函数不会阻塞浏览器绘制视图。
    1. useLayoutEffect
    • useLayoutEffect采用了同步执行, 是在DOM 绘制之前执行。
    • useLayoutEffect callback 中代码执行会阻塞浏览器绘制。

    Q: useEffect和 componentDidMount / componentDidUpdate 执行时机有什么区别 ?

    A: useEffect是异步执行, 不会阻塞浏览器绘制。componentDidMount / componentDidUpdate 是同步执行的

    如何使用useEffect替代componentDidMount?

    A:

    React.useEffect(()=>{
        /* 请求数据 , 事件监听 , 操纵dom */
    },[])  /* 切记 dep = [] */
    

    ß

  • 相关阅读:
    阿里云上的Centos 7.6的一次Nginx+Mysql+PHP7.3 部署
    Spring系列-SpringBoot 学习路径
    想做公众号,总要写点什么--第008期博文
    我关注的那些公众号-第007期博文
    Ruby on Rails,一对多关联(One-to-Many)
    ruby新建web项目步骤,使用mysql数据库
    ruby select 方法,可用于先查询结果后,再次用条件限制
    cron和crontab命令详解 crontab 每分钟、每小时、每天、每周、每月、每年定时执行 crontab每5分钟执行一次
    nginx做rails项目web服务器缓存配置方法
    ruby----%使用法
  • 原文地址:https://www.cnblogs.com/renzhiwei2017/p/15617496.html
Copyright © 2011-2022 走看看