React 的生命周期

React v16.0前的生命周期

其实大部分团队不见得会跟进升到16版本,所以16前的生命周期还是很有必要掌握的,何况16也是基于之前的修改

在这里插入图片描述

生命周期可分为四个阶段:
1. 组件初始化(initialization)阶段:
- constructor 方法
  1. 组件一创建就会调用 es6 class类中的 constructor 方法(最先执行)
  2. super(props)`用来调用类的构造方法( constructor() ), 也将父组件的props注入给子组件,子组件中props只读不可变,state可变
  3. constructor()用来做一些组件的初始化工作,如定义this.state的初始内容
class TodoList extends Component {
	// 组件一创建最先执行,早于render
	constructor(props) {
		super(props);
		this.state = {
			inputValue: '',
			list: []
		}
	}
}
2. 组件的挂载(Mounting)阶段(已插入真实 DOM)
- componentWillMount 方法

在组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引起组件重新渲染,也可以把写在这边的内容提前到constructor()中,所以项目中很少用

- render 方法

根据组件的props和state(两者的重传递和重赋值,无论值是否有变化,都可以引起组件重新render) ,当父组件的 render 函数被运行时, 它的子组件的 render 函数也会被重新运行

return 一个React元素(描述组件,即JSX模板),不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用),不能在里面执行this.setState,会有改变组件状态的副作用。

- componentDidMount 方法

组件挂载到DOM后调用,且只会被调用一次

3. 组件的更新(Updating)阶段
- componentWillReceiveProps 方法(nextProps)

(只跟父组件传过来的 props 的变化有关,所以只有能接受 props 参数的子组件才有这个方法)

此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props

而且这个组件第一次存在于父组件的是时候不会被执行(就是第一次不会执行,以后如果 nextProps 参数有变化才会被执行

class Child extends Component {
    constructor(props) {
        super(props);
        this.state = {
            someThings: props.someThings
        };
    }
    componentWillReceiveProps(nextProps) { // 父组件重传props时就会调用这个方法
        this.setState({someThings: nextProps.someThings});
    }
    render() {
        return <div>{this.state.someThings}</div>
    }
}
- shouldComponentUpdate(nextProps, nextState) 方法

此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能。

   shouldComponentUpdate(nextStates){ // 应该使用这个方法,否则无论state是否有变化都将会导致组件重新渲染
        if(nextStates.someThings === this.state.someThings){
          return false
        }
    }
- componentWillUpdate(nextProps, nextState) 方法

此方法在调用render方法前执行,在这边可执行一些组件更新发生前的工作,一般较少用

- render 方法

render方法在上文讲过,这边只是重新调用

- componentDidUpdate(prevProps, prevState)

此方法在组件更新后被调用,可以操作组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state

4. 卸载阶段
- componentWillUnmount 方法

此方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清楚组件中使用的定时器,清楚componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。

完整的生命周期在 React 组件中的应用
class TodoList extends Component {

  constructor(props) {
    console.log('constructor');
    super(props);
    this.state = {
      list: [],
      inputValue: ''
    }
  }

  // 组件加载前
  componentWillMount() {
    console.log('componentWillMount');
  }

  // nextProps 参数变化后执行 第一次不执行
  componentWillReceiveProps(nextProps) { // 只有子组件有
    console.log('componentWillReceiveProps');
  }

  // shouldComponentUpdate 在组件更新前比较参数和数据,自己返回布尔值,优化组件性能 
  shouldComponentUpdate(nextStates){
    console.log('shouldComponentUpdate');
    return true;
    // if(nextStates.someThings === this.state.someThings){
    //   return false
    // }
}

  // componentWillUpdate 在 render 前执行
  componentWillUpdate() {
    console.log('componentWillUpdate');
  }

  // 生成描述文件 和 渲染
  render() {
    console.log('render');
    return (
      <Fragment>
        <div className="App">
          <div className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
          </div>
          <div>
          <input className='target' value={this.state.inputValue} onChange={this.handleInputChange} />
          <button className='red-btn' onClick={this.handleBtnClick}>add</button>
          </div>
          <ul>
            {
              this.getTodoItems()
            }
          </ul>
        </div>
      </Fragment>
    );
  }

  // 组件加载后
  componentDidMount() {
    console.log('componentDidMount');
  }

  // componentDidUpdate 在组件更新后被调用
  componentDidUpdate() {
    console.log('componentDidUpdate');
  }


  // componentWillUnmount 在组件被卸载前调用
  componentWillUnmount() {
    console.log('componentWillUnmount');
  }
}

React v16.4 的生命周期

在这里插入图片描述

新引入了两个新的生命周期函数
- getDerivedStateFromProps 方法

在组件创建时和更新时的render方法之前调用,它应该返回一个对象来更新状态,或者返回null来不更新任何内容

- getSnapshotBeforeUpdate 方法

在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()

class ScrollingList extends React.Component {
  constructor(props) {
    super(props);
    this.listRef = React.createRef();
  }

  getSnapshotBeforeUpdate(prevProps, prevState) {
    // 我们是否在 list 中添加新的 items ?
    // 捕获滚动​​位置以便我们稍后调整滚动位置。
    if (prevProps.list.length < this.props.list.length) {
      const list = this.listRef.current;
      return list.scrollHeight - list.scrollTop;
    }
    return null;
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    // 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
    // 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
    //(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
    if (snapshot !== null) {
      const list = this.listRef.current;
      list.scrollTop = list.scrollHeight - snapshot;
    }
  }

  render() {
    return (
      <div ref={this.listRef}>{/* ...contents... */}</div>
    );
  }
}

在上述示例中,重点是从 getSnapshotBeforeUpdate 读取 scrollHeight 属性,因为 “render” 阶段生命周期(如 render)和 “commit” 阶段生命周期(如 getSnapshotBeforeUpdatecomponentDidUpdate)之间可能存在延迟。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值