ReactReact入门--生命周期

Posted 晴♡栀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ReactReact入门--生命周期相关的知识,希望对你有一定的参考价值。

🎀个人主页:努力学习前端知识的小羊
感谢你们的支持:收藏🎄 点赞🍬 加关注🪐

文章目录

React生命周期

react生命周期分为三个阶段—初始化阶段运行中阶段销毁阶段

react旧生命周期流程图如下:

初始化阶段

  • componentWillMount: 组件将要挂载,初始化数据的作用,只调用一次 , render之前最后一次修改状态的机会(不安全)
  • render:挂载组件,只能访问this.props和this.state,不允许修改状态和DOM输出
  • componentDidMount: 组件挂载完成,成功render并渲染完成真实DOM之后触发,可以修改DOM
    可以用于数据请求axios,订阅函数调用,给予创建的dom进行初始化,开启定时器
UNSAFE_componentWillMount()
        console.log("第一次将要挂载",this.state.name,document.getElementById('myname').innerhtml);

// 第一次上树前的最后一次修改状态机会
        this.setState(
            name:'Kerwin'
        )

        //初始化数据的作用
    
    componentDidMount()
        console.log('第一次已经挂载',document.getElementById('myname').innerHTML);
        // 数据请求axios
        // 订阅函数调用
        // setInternal
        //基于创建的dom进行 初始化...BetterScoll
    

运行中阶段

  • componentWillUpdate: 更新前的数据状态(不安全),不能修改属性和状态
  • componentDidUpdate:可以修改Dom,每次更新都会执行一次 含有两个属性:prevProps:旧的属性,prevState:旧的状态
  • render:组件更新 shouldComponentUpdate: 决定是否进行更新return true:应该更新,return false:阻止更新 含有两个参数:nextProps:新属性,nextState:新状态
  • componentWillReceiveProps: 最先获得父组件传来的属性,父组件一修改便会触发(非首次)

componentWillUpdatecomponentDidUpdate使用

//   不安全
  UNSAFE_componentWillUpdate()
    console.log("componentWillUpdate",document.getElementById('myname').innerHTML);
  

// 每次更新都会执行一次
  componentDidUpdate(prevProps,prevState)   //prevProps:老的属性
    console.log("componentDidUpdate",document.getElementById('myname').innerHTML);

    // 更新后,想要获取dom节点,更新
    new BScroll('#wrapper')
    console.log(prevProps,prevState);

    //进行判断,只调用一次
    if(prevState.list.length === 0)
        new BScroll("#wrapper")
    
  

shouldComponentUpdate的使用:

shouldComponentUpdate(nextProps,nextState)
    // return true; //应该更新
    // return false;  //组织更新
    // 老状态:this.state;新状态:nextState;新属性:nextProps

    // 通过状态的字符串是否一样来判断
    if(JSON.stringify(this.state) !== JSON.stringify(nextState))
        return true;
     else
        return false;
    
  
	

componentWillReceiveProps的使用:

UNSAFE_componentWillReceiveProps(nextProps)
        console.log("componentWillReceiveProps",
        this.props.text,nextProps);

        // 最先获得父组件传来的属性,可以利用属性进行Ajax或逻辑处理
        // 将属性转化为孩子自己的状态
        this.setState(
            title:nextProps.text
        )
    

销毁阶段

componentWillUnmount: 再删除组件之前进行清理作用,如清除挂载的定时器和事件监听器

componentDidMount()
        window.onresize=()=>
            console.log("resize");
        

        this.timer = setInterval(()=>
            console.log(1);
        ,1000)
    
//进行销毁
    componentWillUnmount()
        console.log("componentWillUNMount");
        //取消监听事件
        window.onresize=null
		//清除定时器
        clearInterval(this.timer)
    

老生命周期的问题

  • componentWillMount 在ssr(服务器渲染)中这个方法将会被多次调用,所以会重复触发多遍,同时在这里如果绑定事件,将无法解绑,导致内存泄漏,变得不够安全高效逐步废弃。
  • componentWillReceiveProps外部组件多次频繁更新传入多次不同的props,会导致不必要的异步请求
  • componetwilupdate,更新前记录DOM状态,可能会做一些处理,与componentDidUpdate相隔时间如果过长,会导致状态不太信

新生命周期代替

新生命周期流程图:

static getDerivedStateFromProps :从props得到一个派生状态,第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子),返回一个对象作为新的state,返回null则说明不需要在这里更新state

// 适用于初始化和后续更新
    static getDerivedStateFromProps(nextProps,nextState)
        console.log('getDerivedStateFromProps',nextState);
        return 
            myname:nextState.myname
        
    

getSnapshotBeforeUpdate:在组件更新之前获取快照,即记录更新前的数据和状态,返回的值作为componentDidUpdate的第三个参数

componentDidUpdate = (prevProps, prevState,value) => 
  console.log("componentDidUpdate",value);  //value:100


getSnapshotBeforeUpdate()
    console.log('getSnapshotBeforeUpdate');
    return 100

性能优化的方案

shouldComponentUpdate

控制组件自身或者子组件是否需要更新,尤其在子组件非常多的情况下,需要进行优化

PureComponent

PureComponent会帮你比较新props跟旧的props,新的state和老的state(值相等,或者对象含有相同的属性、且属性值相等),决定shouldcomponentUpdate返回true或者false,从而决定要不要呼叫render function。

import React,  PureComponent  from 'react'

export default class App extends PureComponent 


注意: 如果你的state或 props『永远都会变』,那 PureComponent并不会比较快,因为shallowEqual 也需要花时间。

重要的勾子

  • render:初始化渲染或更新渲染调用

  • componentDidMount:开启监听,发送axios请求

  • componentWillUnmount:做一些收尾工作,如清理定时器和事件监听器

即将废弃的勾子

  • componentWillMount

  • componentWillReceiveProps

  • componentWillUpdate

注:使用时会出现警告,需要加上UNSAFE_前缀才能使用,以后可能被弃用

希望能够对学习react的小伙伴们有所帮助,期待你们的支持哦✨✨✨

ReactReact全家桶React 生命周期+虚拟DOM+Diff算法

文章目录

1 React 生命周期

React的生命周期:React实例从被创建到被销毁的过程,React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。

只有 class 组件才有生命周期,因为 class 组件会创建对应的实例,而函数组件不会 。

React 生命周期主要包括三个阶段:初始化(挂载)阶段,更新阶段,销毁(卸载)阶段

1.1 初始化阶段

初始化(挂载)阶段:组件实例被创建和插入 DOM 树的过程

由ReactDOM.render()触发初次渲染

  • constructor():类组件构造函数,在组件挂载之前调用;仅用于初始化内部state以及为事件处理函数绑定实例
  • getDerivedStateFromProps() :会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用,此方法适用于state 的值在何时候都取决于 props【新增】
  • render():初始化渲染或更新渲染调用,是 class 组件中唯一必须实现的方法;
  • componentDidMount():会在组件挂载后(插入 DOM 树中)立即调用;

1.2 更新阶段

由组件内部this.setSate()或父组件重新render触发或强制更新forceUpdate()

  • getDerivedStateFromProps(): 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用,此方法适用于state 的值在何时候都取决于 props【新增】
  • shouldComponentUpdate() :根据该函数的返回值,来确定组件是否重新渲染
  • render(): 初始化渲染或更新渲染调用,是 class 组件中唯一必须实现的方法;
  • getSnapshotBeforeUpdate():在最近一次渲染输出(提交到 DOM 节点)之前调用;此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate();
  • componentDidUpdate():会在更新后会被立即调用,首次渲染不会执行此方法;

1.3 卸载阶段

ReactDOM.unmountComponentAtNode()触发

  • componentWillUnmount() :会在组件卸载及销毁之前直接调用;

1.4 重要的勾子

  • render:初始化渲染或更新渲染调用。
  • componentDidMount:在组件挂载成功之后调用,该过程组件已经成功挂载到了真实 DOM 上。一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  • componentWillUnmount:在组件卸载成功之前调用,做一些收尾工作, 如: 清理定时器

1.5 已经废弃的勾子

  1. componentWillMount
  2. componentWillReceiveProps
  3. componentWillUpdate

使用会出现警告,在React 18.0需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。

2 虚拟DOM、Diff算法

2.1 原生JS和React渲染页面的区别

原生JS渲染页面:数据 => 真实DOM

React渲染页面:数据 => 虚拟DOM(内存中的数据)=> 真实DOM

优点:减少了DOM操作,减少了回流与重绘,保证性能的下限,比正常的DOM性能更好

缺点:首次渲染DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢。

2.2 虚拟DOM

虚拟DOM是JS按DOM(真实DOM)的结构来创建的虚拟树型结构对象,是对DOM的抽象,比DOM更加轻量型(属性更少), 只保留了真实 DOM 节点的一些基本属性,和节点之间的层次关系, 本质还是Object类型的对象,虚拟DOM最终会被React转化为真实DOM,呈现在页面上。 虚拟DOM会通过ReactDOM.render进行渲染成真实DOM。

2.3 Diff算法

Diff算法原理图

React 通过Diff算法只更新它需要更新的部分,React DOM 会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使 DOM 达到预期的状态。

Key 是虚拟DOM对象的标识,主要用在Diff算法中,每个虚拟节点都有一个唯一标识Key,通过对比新旧节点的key来判断节点是否改变,可以大大提高渲染效率。

Diff算法是用于比较新旧虚拟节点之间差异的一种算法,每个虚拟节点都有一个唯一标识key,通过对比新旧节点的key来判断节点是否改变,将两个节点不同的地方存储在patch对象中,最后利用patch记录的消息局部更新DOM。 比较规则如下 :

  • 旧虚拟DOM中找到了与新虚拟DOM相同的key:

    • 若虚拟DOM中内容没变, 直接使用之前的真实DOM
    • 若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
  • 旧虚拟DOM中未找到与新虚拟DOM相同的key:

    • ​ 根据数据创建新的真实DOM,随后渲染到到页面

用index作为key可能会引发的问题:

  • 若对数据进行:逆序添加、逆序删除等破坏顺序操作,会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
  • 如果结构中包含输入类的DOM,会产生错误DOM更新 ==> 界面有问题
  • 仅用于渲染列表用于展示,使用index作为key是没有问题的

开发中如何选择key?

  • 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值
  • 如果确定只是简单的展示数据,用index也是可以的

由下图可知,第一次有三项数据渲染为真实DOM,第二次渲染中的数据比第一次多了一项,此时React使用Diff算法按照规则在虚拟DOM中依次对比每一项数据,发现前三项数据key和内容都相同,则复用第一次的真实DOM,最后一项数据没有则需渲染新数据为真实DOM,提高了渲染效率。

以上是关于ReactReact入门--生命周期的主要内容,如果未能解决你的问题,请参考以下文章

ReactReact全家桶React 生命周期+虚拟DOM+Diff算法

React组件安装使用和生命周期函数

Vue 入门-生命周期

Maven入门教程三----生命周期和插件

Vue入门必备知识篇03--- 生命周期 & 数据共享

maven入门maven的生命周期