资源

  • 组件的生命周期:组件的生命周期详解。

    1. [生命周期小结](https://www.jianshu.com/p/4784216b8194):总结<br /> [生命周期图形版](https://www.jianshu.com/p/4784216b8194):ReactNative 生命周期图形案例结合版<br /> [生命周期](https://www.jianshu.com/p/4784216b8194):React 生命周期菜鸟教程<br /> [使用组件原因](https://segmentfault.com/a/1190000011197112#articleHeader2):使用组件和生命周期的原因[1](https://segmentfault.com/a/1190000011197112#articleHeader2)、[2](http://axuebin.com/blog/2017/09/15/react-lifecycle/#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%B5%81%E7%A8%8B%E5%9B%BE)<br /> [使用生命周期原因](https://segmentfault.com/a/1190000014487297): 使用原因详解

    组件

    可以使用函数定义了一个组件:

    1. function HelloMessage(props) {
    2. return <h1>Hello World!</h1>;}

你也可以使用 ES6 class 来定义一个组件:

  1. class Welcome extends React.Component {
  2. render() {return <h1>Hello World!</h1>;}}
  • const element = 为用户自定义的组件。

    1. 注意:原生html元素名小写字母开头,自定义的 React 大写字母开头。组件类只能包含一个顶层标签,否则也 会报错。<br /> 如果需要向组件传递参数,可以使用 **this.props** 对象
  • 将生命周期方法添加到类中

    1. 在具有许多组件的应用程序中,在销毁时释放组件所占用的资源非常重要。<br /> 每当 Clock 组件第一次加载到 DOM 中的时候,都想生成定时器,这在 React 中被称为**挂载**。<br /> 同样,每当 Clock 生成的这个 DOM 被移除的时候,也会想要清除定时器,这在 React 中被称为**卸载**。<br /> 可以在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码

    生命周期

    image.png

一个React组件的生命周期分为三个部分:实例化、存在期和销毁时。
实例化
当组件在客户端被实例化,第一次被创建时,以下方法依次被调用:
(1)getDefaultProps (2)getInitialState (3)componentWillMount
(4)render (5)componentDidMount
当组件在服务端被实例化,首次被创建时,以下方法依次被调用:
(1)getDefaultProps (2)getInitialState (3)componentWillMount (4)render
componentDidMount 不会在服务端被渲染的过程中调用

存在期
此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用
(1)componentWillReceiveProps (2)shouldComponentUpdate (3)componentWillUpdate
(4)render (5)componentDidUpdate

销毁时 componentWillUnmount
每当React使用完一个组件,这个组件必须从 DOM 中卸载后被销毁,此时 componentWillUnmout 会被执行,完成所有的清理和销毁工作,在 componentDidMount 中添加的任务都需要再该方法中撤销,如创建的定时器或事件监听器。
当再次装载组件时,以下方法会被依次调用:
(1)getInitialState (2)componentWillMount (3)render (4)componentDidMount

反模式
在 getInitialState 方法中,尝试通过 this.props 来创建 state 的做法是一种反模式。

  1. //反模式
  2. getDefaultProps: function(){
  3. return {data: new Date()}},
  4. getInitialState: function(){
  5. return {day: this.props.date - new Date()}},
  6. render: function(){return <div>Day:{this.state.day}</div>}

经过计算后的值不应该赋给 state,正确的模式应该是在渲染时计算这些值。这样保证了计算后的值永远不会与派生出它的 props 值不同步。

  1. //正确模式
  2. getDefaultProps: function(){
  3. return {data: new Date()}},
  4. render: function(){var day = this.props.date - new Date();
  5. return <div>Day:{day}</div>}

如果只是简单的初始化 state,那么应用反模式是没有问题的

总结
image.png

细节

在ES6中,一个React组件是用一个class来表示的(具体可以参考官方文档),如下:

  1. // 定义一个TodoListReact组件,通过继承React.Component来实现
  2. class TodoList extends React.Component {
  3. ...
  4. }
  • 生命周期的方法有:

componentWillMount 在渲染前调用,在客户端也在服务端。
componentDidMount : 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
可以在你确认不需要更新组件时使用。
componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
componentWillUnmount在组件从 DOM 中移除之前立刻被调用。

  • 这几个生命周期相关的函数有:

    1. constructor(props, context)

    构造函数,在创建组件的时候调用一次。

    1. void componentWillMount()

    在组件挂载之前调用一次。如果在这个函数里面调用setState,本次的render函数可以看到更新后的state,并且只渲染一次。

    1. void componentDidMount()

    在组件挂载之后调用一次。这个时候,子主键也都挂载好了,可以在这里使用refs。

    1. void componentWillReceiveProps(nextProps)

    props是父组件传递给子组件的。父组件发生render的时候子组件就会调用componentWillReceiveProps(不管props有没有更新,也不管父子组件之间有没有数据交换)。

    1. bool shouldComponentUpdate(nextProps, nextState)

    组件挂载之后,每次调用setState后都会调用shouldComponentUpdate判断是否需要重新渲染组件。默认返回true,需要重新render。在比较复杂的应用里,有一些数据的改变并不影响界面展示,可以在这里做判断,优化渲染效率。

    1. void componentWillUpdate(nextProps, nextState)

    shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillUpdate会被调用。

    1. void componentDidUpdate()

    除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。
    componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以对应起来。区别在于,前者只有在挂载的时候会被调用;而后者在以后的每次更新渲染之后都会被调用。

    1. ReactElement render()

    render是一个React组件所必不可少的核心函数(上面的其它函数都不是必须的)。记住,不要在render里面修改state。

    1. void componentWillUnmount()

    组件被卸载的时候调用。一般在componentDidMount里面注册的事件需要在这里删除。

  • 更新方式

    在react中,触发render的有4条路径。
    以下假设shouldComponentUpdate都是按照默认返回true的方式。
    (1)首次渲染Initial Render
    (2)调用this.setState (并不是一次setState会触发一次render,React可能会合并操作,再一次性进行 render)
    (3)父组件发生更新(一般就是props发生改变,但是就算props没有改变或者父子组件之间没有数据交换也会触 发 render)
    (4)调用this.forceUpdate

  • React组件四条更新路径
    image.png