React生命周期

React生命周期

初始化

在组件初始化阶段会执行

  1. constructor

    1. 通过super来继承父类身上传递过来的属性,让后当前组件通过this.props接收
    2. 用来初始化一个状态
    3. 用来初始化绑定一个方法,将this传递给这个方法

    注意:
    不写方法的触发( 订阅 )
    不写具有副作用的代码( 比如: 计时器 )

  2. static getDerivedStateFromProps()
    17版本将来会使用

    1. 数据请求
    2. 数据修改
      返回值就是修改后的数据
  3. componentWillMount() / UNSAFE_componentWillMount()

    1. 提供了一次 数据修改机会
    2. 进行数据请求
      axios
      fetch

    注意:
    虽然我们这里可以进行数据请求和初始化数据的修改,但是官方建议我们写在componentDidMount中
    可以减少副作用和订阅

  4. render()

    1. 计算this.prop this.state
    2. 返回一种类型
      1. React元素。通过jsx创建,既可以是dom元素,也可以是用户自定义的组件。
      2. 字符串或数字。他们将会以文本节点形式渲染到dom中。
      3. Portals【'portl】。react 16版本中提出的新的解决方案,可以使组件脱离父组件层级直接挂载在DOM树的任何位置。
      4. null,什么也不渲染
      5. 布尔值。也是什么都不渲染。
    3. render()方法必须是一个纯函数,他不应该改变state,也不能直接和浏览器进行交互,应该将事件放在其他生命周期函数中。
    4. 如果shouldComponentUpdate()返回false,render()不会被调用。
    5. jsx->vdom 对象
  5. componentDidMount()
    组件挂载结束
    可以实现:

    1. 数据请求
    2. 数据修改
    3. 将render函数生成的vdom对象渲染成真实dom,然后挂载在 id 为 root 的容器中

初始化阶段代码:

import React,{ Component,Fragment } from 'react'
import ErrorBoundary from './Error'

class Father extends Component{

  constructor ( props ) {
    super( props )            
    this.state = {
      msg : 'hello React.js'
    }
  }

  changeMsg = () => {
    this.setState({
      msg: 'hello 篮球'
    })
  }

  render () {
    return (
      <Fragment>
        <h3> Father组件 - 更新阶段</h3>
        <button onClick = { this.changeMsg }> changemsg </button>
        <p> constructor : { this.state.msg } </p>
        <p> money: { this.props.money } </p>
        <ErrorBoundary {...this.props}></ErrorBoundary>
      </Fragment>
    )
  }

  // componentWillReceiveProps ( nextProps ) {
  //  console.log( 'componentWillReceiveProps ');
  //  console.log( nextProps );//属性变化之后的值
  // }

  shouldComponentUpdate () {
    
    // return false/true
    return true

  }
 
  //当shouldComponentUpdate 返回值为 true时,下面钩子才能执行

  // componentWillUpdate () {

  // }

  getSnapshotBeforeUpdate () {
   console.log( 'getSnapshotBeforeUpdate' )
    return 1000
  }
  componentDidUpdate ( preState,preProps,snapshot ) {
    console.log('snapshot',snapshot )
    fetch( '/data.json' )
      .then( res => res.json())
      .then( data => console.log( 'componentDidUpdate',data ))
      .catch( error => {
        if( error ) console.log( error )
      })

    document.querySelector('h3').style.background = 'red'

    console.log( 'componentDidUpdate' )
  }

  componentDidCatch ( error , info ) {
    console.log( 'father',info )
  }

}

export default Father   

更新阶段

propsstate的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法:

  1. componentWillReceiveProps() / UNSAFE_componentWillReceiveProps()
    触发: 属性发生改变,就会触发
    这个钩子函数一定能监听到整个当前组件的属性变化 — > 当前组件的路由我们也可以监听到
    应用场景:
    1. 路由监听

  2. static getDerivedStateFromProps()

  3. shouldComponentUpdate() // react性能优化第二方案
    决定组件是否更新
    返回值true,更新
    返回值false,不更新
    默认值是true
    这个钩子是React性能优化的关键钩子

  4. componentWillUpdate() / UNSAFE_componentWillUpdate()
    组件即将更新
    生成新的VDOM

  5. render()

  6. getSnapshotBeforeUpdate()

  7. componentDidUpdate()
    组件更新结束

    1. 数据请求
    2. DOM操作( 第三方库的实例化 )
    3. 接收 getSnapshotBeforeUpdate() 第三个参数作为返回值

    使用fiber算法进行 新vdom和旧的vdom对比,生成新的patch对象

    在根据patch对象进行页面渲染

更新阶段代码:

import React,{ Component,Fragment } from 'react'


class Father extends Component{

  constructor ( props ) {
    super( props )            
    this.state = {
      msg : 'hello React.js'
    }
  }

  changeMsg = () => {
    this.setState({
      msg: 'hello 篮球'
    })
  }

  render () {
    return (
      <Fragment>
        <h3> Father组件 - 更新阶段</h3>
        <button onClick = { this.changeMsg }> changemsg </button>
        <p> constructor : { this.state.msg } </p>
        <p> money: { this.props.money } </p>
      </Fragment>
    )
  }

  componentWillReceiveProps ( nextProps ) {
   console.log( 'componentWillReceiveProps ');
   console.log( nextProps );//属性变化之后的值
  }

  shouldComponentUpdate () {
    // return false/true
    return true

  }
 
  //当shouldComponentUpdate 返回值为 true时,下面钩子才能执行

  componentWillUpdate () {
    /* 
      组件即将更新   
        生成新的VDOM
    */
  }

  // render 函数     jsx --> vdom对象

  componentDidUpdate ( ) {
    /* 
      组件更新结束
        1. 数据请求
        2. DOM操作( 第三方库的实例化 )
        3. 接收 getSnapshotBeforeUpdate() 第三个参数作为返回值

      使用fiber算法进行 新vdom和旧的vdom对比,生成新的patch对象

      在根据patch对象进行页面渲染

    */

    fetch( '/data.json' )
      .then( res => res.json())
      .then( data => console.log( 'componentDidUpdate',data ))
      .catch( error => {
        if( error ) console.log( error )
      })

    document.querySelector('h3').style.background = 'red'

    console.log( 'componentDidUpdate' )
  }

}

export default Father   

卸载阶段

  1. componentWillUnmount()
    组件销毁:
    外部销毁: 开关 【推荐】
    内部销毁:
    ReactDOM.unmountComponentAtNode( document.querySelector(’#root’) ) //必须是root

卸载阶段代码:

import React,{ Component,Fragment } from 'react'
import ReactDOM from 'react-dom'


class Father extends Component{

  constructor ( props ) {
    super( props )            
    this.state = {
      msg : 'hello React.js'
    }
  }

  destory = () => {
    ReactDOM.unmountComponentAtNode( document.querySelector('#root') ) //必须是root
  }
  render () {
    return (
      <Fragment>
        <div className = "father-box">

          <h3> Father组件 - 更新阶段</h3>
          <button onClick = { this.destory }> 内部销毁 </button>
          <p> constructor : { this.state.msg } </p>
          <p> money: { this.props.money } </p>
        </div>
      </Fragment>
    )
  }

  componentWillUnmount () {
    /* 
      组件销毁
        外部销毁: 开关 【推荐】
        内部销毁: 
          ReactDOM.unmountComponentAtNode( document.querySelector('#root') ) //必须是root

    */
    console.log( 'componentWillUnmount' )
  }

}

export default Father   

错误处理

  1. componentDidCatch()

报错阶段代码:

import React from 'react'

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: true };
  }

  static getDerivedStateFromError(error) {
    // 更新 state 使下一次渲染可以显示降级 UI
    console.log( 'getDerivedStateFromError ')
    return { hasError: true };
  }

  componentDidCatch(error, info) {
    // "组件堆栈" 例子:
    //   in ComponentThatThrows (created by App)
    //   in ErrorBoundary (created by App)
    //   in div (created by App)
    //   in App
    // logComponentStackToMyService(info.componentStack);
    console.log( 'info',info )
  }

  changeHasError = () => {
    this.setState({
      hasError: !this.state.hasError
    })
  }

  render() {

    if (this.state.hasError) {
      // 你可以渲染任何自定义的降级 UI
      return (
        <div>
          <h1>Something went wrong.</h1>
          <button onClick = { this.changeHasError }> 点击 </button>
        </div>
      );
    }

    return <div>  其他子组件正常  </div>; 
  }
}

export default ErrorBoundary
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值