zoukankan      html  css  js  c++  java
  • react的生命周期和使用

    image.png

    完整的生命周期

    我们都知道生命周期分为三个大阶段:

    1. 挂载
    2. 更新
    3. 卸载


    挂载的时候我们我们有 constructor 、 getDerivedStateFromProps 、render 、 componentDidMount (即将被废弃的生命周期不再写入,也不推荐大家继续使用)

    挂载

    constructor

    它一般用于初始化state和绑定事件,只有在这里对state赋值直接赋值,而且最好不要在这里进行副作用的操作,后面会做解释。还有不要将props直接赋值给state

      constructor(props) {
        super(props);
        this.state = {
          name: this.props.name,
        };
      }
    


    这种写法不会及时的更新状态

    如下:

    // 父组件
    import React, {Component} from "react";
    import Son from "./son";
    
    class App extends Component {
      constructor() {
        this.state = {
          number: 0,
        };
      }
      render() {
        const {number} = this.state;
        return (
            <div>
              <button onClick={() => this.setState({number: number + 1})}>add</button>
              <br/>
              <Son name={this.state.number}/>
            </div>
        );
      }
    }
    
    export default App;
    
    // 子组件
    import React, {Component} from "react";
    
    class Son extends Component {
      constructor(props) {
        super(props);
        this.state = {
          name: this.props.name,
        };
      }
    
      render() {
        return (
            <div>
              <p>将props赋值给了子组件state</p>
              {this.state.name}
              <br/>
              <p>直接使用了this.props.number</p>
              {this.props.name}
            </div>
        );
      }
    }
    
    export default Son;
    

    父组件点击一次以后,子组件中直接使用 this.props.number  的更新了,而通过赋值给state的没有更新。


    image.png



    -------------------------------------------------------------------------------------------------------------------**

    getDerivedStateFromProps



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

    render


    此方法在挂载阶段肯定会被调用,而在更新阶段会取决于 UNSAFE_componentWillUpdate和shouldComponentUpdate()返回值影响

    它应该返回以下类型之一

    • React 元素。通常通过 JSX 创建。例如,<div /> 会被 React 渲染为 DOM 节点,<MyComponent /> 会被 React 渲染为自定义组件,无论是 <div /> 还是 <MyComponent /> 均为 React 元素。
    • 数组或 fragments。 使得 render 方法可以返回多个元素。欲了解更多详细信息,请参阅 fragments 文档。
    • Portals。可以渲染子节点到不同的 DOM 子树中。欲了解更多详细信息,请参阅有关 portals 的文档
    • 字符串或数值类型。它们在 DOM 中会被渲染为文本节点
    • 布尔类型或 null。什么都不渲染。(主要用于支持返回 test && <Child /> 的模式,其中 test 为布尔类型。)

    componentDidMount

    会在组件挂载到dom上的时候立即调用,如果这个时候调用setState的话会再次触发render,但是会在屏幕更新出来之前完成渲染。下面示例:

    import React, {Component} from "react";
    
    class SonTwo extends Component {
      constructor(props) {
        super(props);
        this.state = {
          number: 0,
        };
      }
    
      componentDidMount() {
        this.setState({
          number: this.state.number + 1,
        });
      }
    
      render() {
        console.log("我执行了", this.state.number);
        return (
            <div>
              {this.state.number}
            </div>
        );
      }
    }
    
    export default SonTwo;
    
    


    ![image.png](https://cdn.nlark.com/yuque/0/2020/png/425103/1586445215750-938b1066-9f85-4793-848f-81b1534faa69.png#align=left&display=inline&height=138&name=image.png&originHeight=138&originWidth=237&size=4367&status=done&style=shadow&width=237)

    **这里为什么会出现4次,是因为 react的 **[**严格模式**](https://zh-hans.reactjs.org/docs/strict-mode.html#gatsby-focus-wrapper)

    严格模式不能自动检测到你的副作用,但它可以帮助你发现它们,使它们更具确定性。通过故意重复调用以下函数来实现的该操作:

    • class 组件的 constructorrender 以及 shouldComponentUpdate 方法
    • class 组件的生命周期方法 getDerivedStateFromProps
    • 函数组件体
    • 状态更新函数 (即 setState 的第一个参数)
    • 函数组件通过使用 useStateuseMemo 或者 useReducer


    所以使用的时候需要注意如果出现循环更改可能会出现性能问题

    更新

    getDerivedStateFromProps

    shouldComponentUpdate


    每次props或者state变化是render之前它会被调用,默认是正常调用render,但是如果这个周期函数返回false就会停止组件的渲染,不过父组件的state或者props变化不引起本组件改变,其子组件的state改变依然会更新

    // 父组件
    import React, {Component} from "react";
    import Son from "./son";
    
    class App extends Component {
      constructor(props) {
        super(props);
        this.state = {
          number: 0,
        };
      }
      shouldComponentUpdate(nextProps, nextState, nextContext) {
        return nextState.number > 10;
      }
      render() {
        const {number} = this.state;
        return (
            <div style={{border: "1px solid red", margin: "6px"}}>
              <button onClick={() => this.setState({number: number + 1})}>add
              </button>
              <br/>
              <span>父组件中的number: </span>{this.state.number}
              <br/>
              <Son number={this.state.number}/>
              {/*<SonTwo/>*/}
            </div>
        );
      }
    }
    
    export default App;
    
    // 子组件
    import React, {Component} from "react";
    class Son extends Component {
      constructor(props) {
        super(props);
        this.state = {
          number: 0,
        };
      }
      render() {
        return (
            <div style={{border: "1px solid blue", margin: "6px", padding: "20px"}}>
              <button onClick={() => {
                this.setState({
                  number: this.state.number + 1,
                });
              }}>ADD
              </button>
              <br/>
              <br/>
              <span>父组件中的值: </span>{this.props.number}
              <br/>
              <span>子组件中的值: </span>{this.state.number}
            </div>
        );
      }
    }
    export default Son;
    

    效果如图:


    image.png   image.png


    图1 是点击了外层的父节点的add后子节点并没接收到父节点传递过来的值,因为父节点的render并没有被触发。

    图2 是点击了内层的子节点上ADD后发现子组件触发了render

    -------------------------------------------------------------------------------------------------------------------**

    render

    同上

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

    getSnapshotBeforeUpdate

    componentDidUpdate

    在更新结束和被调用,首次渲染不会触发它,首次渲染触发的 componentDidMount 可以做的 DOM 操作或者发起请求,它也可以,只是更新渲染结束后不会再触发componentDidMount, 而触发的是它。可以基于更新前后的state或者props的变化来做出相应的请求或者操作




    重点对于状态的更改需要做出判断

    你也可以在 componentDidUpdate() 中直接调用 setState(),但请注意它必须被包裹在一个条件语句里,正如上述的例子那样进行处理,否则会导致死循环。


    -------------------------------------------------------------------------------------------------------------------**

    卸载

    componentWillUnmount

    componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。
    componentWillUnmount()不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它。

  • 相关阅读:
    centos 搭建git 服务器
    easyui Tree树形控件的异步加载
    iis7 部署 mvc4项目提示404错误
    CS0012: 类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义
    asp.net mvc 自定义身份验证
    asp.net mvc 自定义身份验证 2
    爬取五八同城上房子信息并保存到Excel
    scrapy爬取图片并自定义图片名字
    Scrapy爬取到的中文数据乱码问题处理
    scrapy图片-爬取哈利波特壁纸
  • 原文地址:https://www.cnblogs.com/daixixi/p/12670673.html
Copyright © 2011-2022 走看看