React.js学习笔记之组件生命周期

前端之家收集整理的这篇文章主要介绍了React.js学习笔记之组件生命周期前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

React.js学习笔记之组件生命周期

@(React学习)

什么是组件

React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。

组件类只能包含一个顶层标签,否则会报错。

var HelloXiaowang = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});

ReactDOM.render(
  <HelloXiaowang name="junyan" />,document.getElementById('shuaige')
);

上面代码中,变量 HelloXiaowang 就是一个组件类。模板插入 HelloXiaowang /> 时,会自动生成 HelloXiaowang 的一个实例(下文的"组件"都指组件类的实例)。

render

所有组件类都必须有自己的render方法,用于输出组件
ReactElement render ( )

调用的时候,会检测 this.props 和 this.state,返回一个单子级组件。该子级组件可以是虚拟的本地 DOM 组件(比如 div /> 或者 React.DOM.div()),也可以是自定义的复合组件。

var HelloXiaowang = React.createClass({
  render: function() {
    return <h1>Hello {this.props.name}</h1>;
  }
});

render ( ) 函数应该是纯粹的,也就是说该函数修改组件 s

tate,每次调用都返回相同的结果,不读写 DOM 信息,也不和浏览器交互(例如通过使用 setTimeout)。如果需要和浏览器交互,在 componentDidMount() 中或者其它生命周期方法中做这件事。保持 render() 纯粹,可以使服务器端渲染更加切实可行,也使组件更容易被理解。

生命周期

组件本质上是状态机,输入确定,输出一定确定

状态机本质上是状态与转移的结合。当状态发生转换时会触发不同的钩子函数,从而让开发者有机会做出相应。
组件的声明周期分成三个状态:

  • Mounting:初始化阶段(已插入真实 DOM)

  • Updating:运行中阶段(正在被重新渲染)

  • Unmounting:销毁阶段(已移出真实 DOM)

初始化阶段Mounting

类创建完成之后,就可以进行实例化。

初始化阶段可以使用的函数

  • getDefaultProps: 只调用一次,实例之间共享引用

  • getInitialState: 初始化每个实例特有的状态

  • componentWillMount: render之前最后一次修改状态的机会。如果在这个方法调用setState,render()将会感知到更新后的state,将会执行仅一次,尽管state改变了。

  • render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出

  • componentDidMount: 成功render并渲染完成真实DOM之后触发,可以修改DOM

调用顺序

当组件在客户端被实例化,第一次被创建时,以下方法依次被调用

  1. getDefaultProps

  2. getInitialState

  3. componentWillMount

  4. render

  5. componentDidMount

当组件在服务端被实例化,首次被创建时,以下方法依次被调用

  1. getDefaultProps

  2. getInitialState

  3. componentWillMount

  4. render

componentDidMount 不会在服务端被渲染的过程中调用

实例

getDefaultProps方法不是在组件创建的时候调用,而是在createClass时调用

var count = 0;
var HelloWorld = React.createClass({
    getDefaultProps:function(){
        return {name:"dada"};
    },
    getInitialState:function(){
        return {
            myCount:count++,ready:false
        };
    },
    componentWillMount:function(){
        this.setState({ready:true});
    },
    render:function(){
        return <p>Hello,{this.props.name?this.props.name:"World"}
        <br/>{''+this.props.ready}{this.state.myCount}</p>;
    },componentDidMount:function(){
        $(ReactDOM.findDOMNode(this)).append("bianke");
    }
});
ReactDOM.render(<HelloWorld/>,document.getElementById('shuage'))

阮老师例子:

var Hello = React.createClass({
  getInitialState: function () {
    return {
      opacity: 1.0
    };
  },componentDidMount: function () {
    this.timer = setInterval(function () {
      var opacity = this.state.opacity;
      opacity -= .05;
      if (opacity < 0.1) {
        opacity = 1.0;
      }
      this.setState({
        opacity: opacity
      });
    }.bind(this),100);
  },render: function () {
    return (
      <div style={{opacity: this.state.opacity}}>
        Hello {this.props.name}
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="world"/>,document.body
);

上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。

另外组件的style属性的设置方式要写成style={{opacity: this.state.opacity}}

React.findDOMNode()

如果这个组件已经被初始化到DOM中,这个方法返回相应的原生浏览器的DOM元素。这个方法用于读取这个DOM的值,例如表单的值与DOM的方法。在多数情况下附加一个ref属性与DOM节点上,用来避免使用findDOMNode。当render返回null或false时,findDOMNode也返回null。

注意:

  • findDOMNode是一个用来访问底层DOM节点的出口。在大多数情况下,是不鼓励用出口,因为他穿过了组件的层

  • findDOMNode仅仅是在初始化阶段的组件起作用(因为组件已经存在于DOM结构中)。如果你尝试在尚未在初始化阶段的组件中调用这个方法(就像render()函数中组件尚未创建就调用这个方法)会抛出异常。

  • findDOMNode不能用于没有状态的组件中。

  • getDOMNode已过时,不建议使用。

运行中阶段Updating

此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变

运行中阶段可以使用的函数

  • componentWillReceiveProps:父组件修改属性触发,可以修改属性修改状态。它是在组件发生改变之前触发

  • shouldComponentUpdate:返回false会阻止render调用

  • componentWillUpdate:不能修改属性与状态

  • render: 只能访问this.props和this.state,只有一个顶层组件,不允许修改状态和DOM输出

  • componentDidUpdate:可以修改DOM

componentWillReceiveProps

在组件接收到新的 props 的时候调用。在初始化渲染的时候,该方法不会调用
用此函数可以作为 react 在 prop 传入之后,render()渲染之前更新 state 的机会。老的 props 可以通过this.props获取到。在该函数调用this.setState()将不会引起第二次渲染。

componentWillReceiveProps: function(nextProps) {
  this.setState({
    likesIncreasing: nextProps.likeCount > this.props.likeCount
  });
}

对于 state,没有相似的方法componentWillReceiveState。将要传进来的 prop 可能会引起 state 改变,反之则不然。如果需要在 state 改变的时候执行一些操作,请使 componentWillUpdate

shouldComponentUpdate

在接收到新的 props 或者 state,将要渲染之前调用。该方法在初始化渲染的时候不会调用,在使用 forceUpdate 方法的时候也不会。
如果确定新的 props 和 state 不会导致组件更新,则此处应该 返回 false。

shouldComponentUpdate: function(nextProps,nextState) {
  return nextProps.id !== this.props.id;
}

如果shouldComponentUpdate返回 false,则render()将不会执行,直到下一次 state 改变。

如果性能是个瓶颈,尤其是有几十个甚至上百个组件的时候,使用shouldComponentUpdate可以提升应用的性能

默认情况下shouldComponentUpdate总会返回 true,在 state 改变的时候避免细微的 bug,但是如果总是小心地把 state 当做不可变的,在render()中只从 props 和 state 读取值,此时你可以覆盖shouldComponentUpdate方法,实现新老 props 和 state 的比对逻辑。

componentWillUpdate

在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用。使用该方法做一些更新之前的准备工作。

你不能在此方法中使用this.setState()。如果需要更新 state 来响应某个 prop 的改变,请使用componentWillReceiveProps

componentDidUpdate

在组件的更新已经同步到 DOM 中之后立刻被调用。该方法不会在初始化渲染的时候调用。使用该方法可以在组件更新之后操作 DOM 元素。

调用顺序

每次修改 state,都会重新渲染组件,实例化后通过 state 更新组件,会依次调用下列方法

  1. shouldComponentUpdate

  2. componentWillUpdate

  3. render

  4. componentDidUpdate

但是不要直接修改 this.state,要通过 this.setState 方法修改

实例

正确用法

var HelloXianrou = React.createClass({
    componentWillReceiveProps:function(newProps){
        console.log(newProps);
    },render:function () {
        console.log(4);
        return <p>Hello {this.props.name||"World"}</p>
    },componentDidUpdate:function () {
        $(ReactD.findDOMNode(this)).append("<p>大大是大帅哥</p>")
    }
});
var HelloDada = React.createClass({
    getInitialState:function () {
        return {name:''};
    },handleChange:function (e) {
        this.setState({name:e.target.value});
    },render:function () {
        return <div>
        <HelloXianrou name={this.state.name}></HelloXianrou>
        <br/>
        <input type="text" onChange={this.handleChange} />
        </div>
    }
});
ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))

销毁阶段Unmounting

销毁阶段可以使用的函数

componentWillUnmount:在删除组件之前进行清理操作,比如计时器和事件监听器。或者清除在 componentDidMount 中创建的 DOM 元素。

ReactDOM.unmountComponentAtNode

移除一个已经初始化DOM过的React组件,清理它的操作和状态。如果这个组件中没有初始化过的组件,这个方法没有任何作用。如果这个组件被销毁则返回true,反之返回false

实例

var HelloXianrou = React.createClass({
    render:function () {
        console.log(4);
        return <p>Hello {this.props.name||"World"}</p>
    },componentWillUnmount:function () {
        console.log("Booooooooooom!!")
    }
});
var HelloDada = React.createClass({
    getInitialState:function () {
        return {name:''};
    },handleChange:function (e) {
    /* if (e.target.value == "123") {
    React.unmountComponentAtNode(document.getElementById('reactDemo')[0]);
    return;
} */
        this.setState({name:e.target.value});
    },render:function () {
        /* if(this.state.name == "123"){
            return <p>123</p>
        } */
        return <div>
        <HelloXianrou name={this.state.name}></HelloXianrou>
        <br/>
        <input type="text" onChange={this.handleChange} />
        </div>
    }
});
ReactDOM.render(<HelloDada></HelloDada>,document.getElementById('reactDemo'))

小结

本文主要介绍了组件的生命周期。许多方法在组件生命周期中某个确定的时间点执行。

特别感谢

原文链接:https://www.f2er.com/react/307108.html

猜你在找的React相关文章