React生命周期详解

React 摒弃了十分消耗性能的手动DOM操作,通过控制组件state和props的改变 利用 diff算法 改变DOM,当DOM需要变动,都会先在虚拟DOM上发生,将实际发生变动的部分渲染在真实的DOM上,这样能极大的提高性能
React 中的组件本质上可以理解为是一个状态机,将状态和输出一一对应,这样可以比较直观的反应程序在不同状态时,对应什么样的输出.

组件的 生命周期 由3个部分组成:初始化阶段,运行中阶段,销毁阶段,每个阶段React都提供了不同的钩子函数供开发者使用

初始化阶段

  • getDefaultProps 初始化组件属性的默认值,只调用一次 , 该方法返回一个对象并缓存起来。然后与父组件指定的 props 对象合并,最后赋值给 this.props 作为该组件的默认属性
  • getInitialState 初始化每个实例的状态 , 初始化组件的 state 的值。其返回值会赋值给组件的 this.state 属性
  • componentWillMount 组件render之前,可以修改状态.如果此时在 componentWillMount 中调用 setState,是不会触发 reRender,而是进行 state 合并
  • render 根据 state 的值,生成页面需要的虚拟 DOM 结构,并返回该结构
  • componentDidMount 在render完成后 组件渲染到页面时触发 , 对根据虚拟 DOM 结构而生的真实 DOM 进行相应的处理。组件内部可以通过 ReactDOM.findDOMNode(this) 来获取当前组件的节点,然后就可以像 Web 开发中那样操作里面的 DOM 元素了

state属性介绍:
它是用来存储组件自身需要的数据。它是可以改变的,它的每次改变都会引发组件的更新。这也是 ReactJS 中的关键点之一。
即每次数据的更新都是通过修改 state 属性的值,然后 ReactJS 内部会监听 state 属性的变化,一旦发生变化,就会触发组件的 render 方法来更新 DOM 结构。

运行中阶段

  • componentWillReceiveProps 当组件接收到新的 props 时,会触发该函数。在改函数中,通常可以调用 this.setState 方法来完成对 state 的修改。如果此时在 componentWillReceiveProps 中调用 setState,是不会触发 reRender,而是进行 state 合并
  • shouldComponentUpdate 该方法用来拦截新的 props 或 state,然后根据事先设定好的判断逻辑,做出最后要不要更新组件的决定。
  • componentWillUpdate 当上面的方法拦截返回 true 的时候,就可以在该方法中做一些更新之前的操作,进行渲染之前触发 但它不能修改props和state
  • render 根据一系列的 diff 算法,生成需要更新的虚拟 DOM 数据。(注意:在 render 中最好只做数据和模板的组合,不应进行 state 等逻辑的修改,这样组件结构更加清晰)
  • componentDidUpdate 该方法在组件的更新已经同步到 DOM 中去后触发,我们常在该方法中做一 DOM 操作

注意:此时 this.state 虽然获取到更新数据,但只能在内部源码中使用,我们在开发时,若在 componentWillReceiveProps 中调用 setState,那么在 componentWillReceiveProps、shouldComponentUpdate 和 componentWillUpdate 中还是无法获取到更新后的 this.state,即此时访问的this.state 仍然是未更新的数据,只有在 render 和 componentDidUpdate 中才能获取到更新后的this.state。


注意:禁止在 shouldComponentUpdate 和 componentWillUpdate 中调用 setState,会造成循环调用,直至耗光浏览器内存后崩溃。

销毁阶段

  • componentWillUnmount 在销毁操作真正执行之前调用,我们通常会做一些取消事件绑定、移除虚拟 DOM 中对应的组件数据结构、销毁一些无效的定时器等工作。这些事情都可以在这个方法中处理。

示例代码

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        

Hello, world!

It is {this.state.date.toLocaleTimeString()}.

div> ); } } ReactDOM.render( , document.getElementById('root') );

可以用下面这张图,来详细说明 React 组件生命周期中钩子函数 的触发顺序

React生命周期详解_第1张图片

初始化简单的实例

var MyFirstComponent = React.createClass({
  // 只调用一次,实例之间共享引用
  getDefaultProps: function () {
    // 下面的console.log()是在实例化组件时就被调用
    console.log('getDefaultProps, 1'); 
    return {name: 'Tom'};
  },

  // 初始化每个实例特有的状态
  getInitialState: function () {
    console.log('getInitialState, 2');
    return {ready: false};
  },

  // render之前最后一次修改状态的机会
  componentWillMount: function () {
    console.log('componentWillMount, 3');
    this.setState({ready: true});
  },

  // 只能访问this.props和this.state,只有一个顶层组件,不可以修改状态和DOM输出
  render: function () {
    console.log('render, 4');
    return (
      

"textNode"> Hello, {this.props.name ? this.props.name : 'World'}
{'' + this.state.ready}

) }, // 成功render并渲染完成真实DOM之后触发,可以修改DOM componentDidMount: function () { console.log('componentDidMount, 5'); } }); ReactDOM.render( , document.getElementById('example') );

控制台显示的结果如下,可以很直观的看到各个函数的执行顺序
React生命周期详解_第2张图片

运行简单例子

var ChildComponent = React.createClass({
  // 组件将要接受到属性时触发
  componentWillReceiveProps: function () {
    console.log('componentWillReceiveProps 1');
  },

  // 组件是否需要更新,返回false则阻止render调用
  // 这个函数我们一般谨慎使用,只有在性能调优时会使用
  shouldComponentUpdate: function () {
    console.log('shouldComponentUpdate 2');
    return true;
  },

  // 组件接收到新的props或者state后,进行渲染之前触发
  // 但它不能修改props和state
  componentWillUpdate: function () {
    console.log('componentWillUpdate 3');
  },

  render: function () {
    console.log('render, 4');
    return (
      

"myText"> Hello, {this.props.name ? this.props.name : 'World'}

) }, // 在render完成后 组件完成更新渲染到页面时触发 componentDidUpdate: function () { console.log('componentDidUpdate 5'); // 为了演示方便,这里使用了jQuery,需要在HTML中先加载jQuery库 $(this.refs.myText).append("\nI'm here!"); } }); var ParentComponent = React.createClass({ // 初始化状态 getInitialState: function () { return {name: ''} }, handleChange: function (event) { this.setState({name: event.target.value}); }, render: function () { return (
this.state.name} /> "form-control" type="text" onChange={this.handleChange} />
); } }); ReactDOM.render( , document.getElementById('example') );

React生命周期详解_第3张图片

参考资料(https://facebook.github.io/react/docs/react-component.html)

你可能感兴趣的:(react)