【REACT-生命周期】

一、初始化阶段

在这里插入图片描述
官方将componentWillMount废除。在 componentWillMount进行异步请求,能使数据返回的更快。但,componentWillMount 结束后,render 会立刻被触发,但此时componentWillMount中的异步请求结果可能还未返回结果,一单结果返回会重新render,所以说即使在componentWillMount就进行了异步请求,在返回数据后又会重新render,这会导致服务端渲染场景下的冗余请求等额外问题,得不偿失。因此与在componentDidMount来请求没他大差别,所以官方将它废除。

export default class App  extends Component {
  constructor(){
    super()
    this.state = {
      value:'aaa'
    }

  }
   //v16.2已被标记弃用,不推荐使用,主要的原因是因为新的异步架构会导致它被多次调用,所以网络请求以及事件绑定应该放到 componentDidMount 中
  UNSAFE_componentWillMount(){
    console.log('componentWillMount',this.state.value,document.getElementById('li'))

    //第一次上树前的,最后一次修改状态的机会
    this.setState({value:'bbb'})//会调用render函数
    //初始化数据
  }
  componentDidMount(){
    console.log('componentDidMount',this.state.value,document.getElementById('li'))
    //数据请求axios
    //订阅函数调用
    //setInterval
    //基于创建好的dom进行一切初始化
  }
  render() {
    //只能访问this.props和this.state,不允许修改状态和操作dom
    console.log('render')
    return (
      <div>
        <li id='li'>lili</li>
      </div>
    )
  }
}

在这里插入图片描述

二、运行中阶段

在这里插入图片描述

React v16 弃用 componentWillReceiveProps(nextProps)

  • 最先获得父组件传来的props,可以进行ajax或逻辑处理,也可以将获取的属性转化成孩子的状态
  • 这种方式十分适合父子组件的互动,通常是父组件需要通过某些状态控制子组件渲染亦或销毁
//nextProps: 表示下一个props。
UNSAFE_componentWillReceiveProps(nextProps) {
    if (this.props.sharecard_show !== nextProps.sharecard_show){
        //在这里我们仍可以通过this.props来获取旧的外部状态
        //通过新旧状态的对比,来决定是否进行其他方法
        if (nextProps.show){
        }
    }
}

shouldComponentUpdate(nextProps, nextState)

//this.props: 表示上一个props。this.state: 表示上一个state的值。
//nextProps: 表示下一个props。nextState: 表示下一个state的值。
shouldComponentUpdate(nextProps, nextState) {
	//函数默认返回true,返回false会阻止render调用更新
  return this.state.data!== nextState.data
}

React v16 弃用 componentWillUpdate(nextProps, nextState)

//this.props: 表示上一个props。this.state: 表示上一个state的值。
//nextProps: 表示下一个props。nextState: 表示下一个state的值。
UNSAFE_componentWillUpdate(nextProps, nextState) {

}

componentDidUpdate(prevProps, prevState, snapshot)

提示:为避免无限循环或重复调用,所有网络请求和操作dom都必须位于条件语句中

//prevProps: 表示上一个props。prevState: 表示上一个state的值。
//this.props: 表示下一个props。this.state: 表示下一个state的值。
//snapshot:getSnapshotBeforeUpdate()方法返回的值
componentDidUpdate(prevProps, prevState, snapshot) {
	if (prevState.data !== this.state.data) {
	   // Now fetch the new data here.
	 }
}

三、销毁阶段

在这里插入图片描述

componentWillUnmount

react在组件卸载的时候也是遵循render的执行顺序,从最顶层组件逐级向下执行componentWillUnmount生命周期。

componentDidMount() {
	window.onresize = () => {
		console.log('resize')
	}
	//this为当前组件实例,挂载到当前实例上
	this.timer = setInterval(() =>{
		console.log('111111')
	},1000)
}

componentWillUnmount() {
	window.onresize = null
	clearInterval(this.timer)
}

四、老生命周期中的问题

React16 废弃的生命周期有 3 个 will:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate
    废弃的原因,是在 React16 的 Fiber 架构中,可以中间进行暂停重启操作,调和过程会多次执行 will 周期,不再是一次执行,失去了原有的意义。此外,多次执行,在周期中如果有 setState 或 dom 操作,会触发多次重绘,影响性能,也会导致数据错乱. 因而会有 UNSAFE 开头。
    在这里插入图片描述

五、 新生命周期

getDerivedStateFromProps

  • getDerivedStateFromProps(从属性获取派生状态): 第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) ,return返回一个对象与页面当前状态对象组合作为新的state(相同字段的进行修改),返回null则说明不需要在这里更新state
  • 这里为什么使用静态方法(static)呢?使某些生命周期保持静态,以防止不安全地访问实例属性,乱改状态

class Table extends React.Component {
    state = {
        list: []
    }
    static getDerivedStateFromProps (props, state) {
	    //访问不到this
	    //不能使用setState
	    //将props转为状态
        return {
            list: props.list
        }
    }
    render () {
        .... // 展示 list
    }
}

Class ColorPicker extends React.Component {
    state = {
        color: '#000000',
        prevPropColor: ''
    }
    static getDerivedStateFromProps (props, state) {
        if (props.color !== state.prevPropColor) {
            return {
                color: props.color
                prevPropColor: props.color
            }
        }
        return null
    }
    ... // 选择颜色方法
    render () {
        .... // 显示颜色和选择颜色操作
    }
}

因为getDerivedStateFromProps被定义为静态方法,所以不能够间接应用this.×××,因而咱们须要对类进行实例化,才应用类中定义的办法

class InstrumentCommand extends PureComponent {
                 ......
    static getDerivedStateFromProps(nextProps, preState) {
        const {match: {params: {instrumentId}}} = nextProps;
        if (instrumentId !== preState.instrumentId) {
          new InstrumentCommand(nextProps).implementDispatch(instrumentId)
        }
    }
}

getSnapshotBeforeUpdate

  • 取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后,dom渲染之前返回一个值,作为componentDidUpdate的第三个参数

下面的例子是模拟来新邮件后默认滚回到更新前的内容位置,要注意的是这个例子只有在内容未滚动的时候有效,因为新增数据后浏览器会自动帮忙滚回到原先的位置

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

export default class App  extends Component {
  constructor(){
    super()
    this.state = {
      list:[10,9,8,7,6,5,4,3,2,1]
    }
    this.container = createRef();
  }
  //取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后,dom渲染之前返回一个值,作为componentDidUpdate的第三个参数
  getSnapshotBeforeUpdate(){
    console.log('getSnapshotBeforeUpdate')
    return [this.container.current.scrollHeight,this.container.current.scrollTop]
  }
  componentDidUpdate(prevProps,prevState,snapshot) {
    console.log(snapshot)
    this.container.current.scrollTop = this.container.current.scrollHeight - snapshot[0] + snapshot[1]
  }
  // componentDidUpdate(prevProps,prevState,[scrollHeight,scrollTop]) {
  //   this.container.current.scrollTop = this.container.current.scrollHeight - scrollHeight + scrollTop
  // }
 
  render() {
    //只能访问this.props和this.state,不允许修改状态和操作dom
    console.log('render')
    return (
      <div>
        <button onClick={()=>this.setState({list:[...[20,19,18,17,16,15,14,13,12,11],...this.state.list]})}>新增邮件</button>
        <div style={{fontSize:'20px',fontWeight:'blod'}}>邮箱应用</div>
        <ul style={{height:'500px',overflow:'auto'}} ref={this.container}>
          {
            this.state.list.map(item => {
              return <li style={{height:'100px',background:'pink',marginTop:'15px'}} key={item}>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

``
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值