晴明的博客园 GitHub      CodePen      CodeWars     

[react] 生命周期 lifecycle

生命周期 调用次数 能否使用setSate()
defaultProps / getDefaultProps 1(全局调用一次)
constructor / getInitialState 1
componentWillMount 1
render >=1
componentDidMount 1
componentWillReceiveProps >=0
shouldComponentUpdate >=0
componentWillUpdate >=0
componentDidUpdate >=0
componentWillUnmount 1

生命状态:

Mounting:已插入真实DOM节点
Updating:正在重新渲染
Unmounting:已经移出真实节点

Mounting:

Updating:

大致顺序:

两个挂载:

###componentWillMount()

1、服务端和客户端都只调用一次
2、在初始化渲染之前调用

所以,如果这里调用setState,则会在render中感知到state的变化。

###componentDidMount()

1、仅在客户端有效
2、初始化渲染之后立即调用一次

这时已经有成型的DOM树了,所以可以通过this.getDOMNode()来获取DOM

四个更新

###componentWillReciverPros(nextProps)

1、在接收到新的参数(props)时,会被执行
2、在render之前被调用
3、在初始化渲染的时候,不会被调用

若调用this.setState()并不会引起第二次渲染。

###shouldComponentUpdate(nextProps, nextState)

1、在接收到新的 props或state时,调用
2、在render之前被调用
3、初始化渲染不调用

若返回false,则组件不会更新(即render()不会被执行),同时,componentWillUpdate和componentDidUpdate也不会被执行。

###componentWillUpdate(nextProps, nextState)

1、在接收到新的 props或state前,立刻调用
2、初始化渲染不调用

不能使用this.setState

###componentDidUpdate(prevProps, prevState)

1、在组件更新已经同步到DOM上之后调用
2、初始化渲染不调用

一个移除

###componentWillUnmount

在组件将被移出的时候调用

一个React组件的生命周期分为三个部分:实例化、存在期和销毁时。

实例化

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

1、getDefaultProps
2、getInitialState
3、componentWillMount
4、render
5、componentDidMount

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

1、getDefaultProps
2、getInitialState
3、componentWillMount
4、render

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

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

1、shouldComponentUpdate
2、conponentWillUpdate
3、render
4、conponentDidUpdate

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

存在期

此时组件已经渲染好并且用户可以与它进行交互,比如鼠标点击,手指点按,或者其它的一些事件,导致应用状态的改变,你将会看到下面的方法依次被调用

1、componentWillReceiveProps
2、shouldComponentUpdate
3、componentWillUpdate
4、render
5、componentDidUpdate

销毁时

componentWillUnmount

每当React使用完一个组件,这个组件必须从 DOM 中卸载后被销毁,此时 componentWillUnmout 会被执行,完成所有的清理和销毁工作,在 conponentDidMount 中添加的任务都需要再该方法中撤销,如创建的定时器或事件监听器。

当再次装载组件时,以下方法会被依次调用:

1、getInitialState
2、componentWillMount
3、render
4、componentDidMount

生命周期相关的函数有:

constructor(props, context)

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

void componentWillMount()

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

void componentDidMount()

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

void componentWillReceiveProps(nextProps)

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

bool shouldComponentUpdate(nextProps, nextState)

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

void componentWillUpdate(nextProps, nextState)

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

void componentDidUpdate()

除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。

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

ReactElement render()

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

void componentWillUnmount()

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

在react中,触发render的有4条路径。

以下假设shouldComponentUpdate都是按照默认返回true的方式。

首次渲染Initial Render
调用this.setState (并不是一次setState会触发一次render,React可能会合并操作,再一次性进行render)
父组件发生更新(一般就是props发生改变,但是就算props没有改变或者父子组件之间没有数据交换也会触发render)
调用this.forceUpdate
注意,如果在shouldComponentUpdate里面返回false可以提前退出更新路径。

组件的初始化阶段的各个方法

var style = {
  color : "red",
  border : "1px #000 solid",
};

var TextClass = React.createClass({
    getDefaultProps:function(){
        console.log("getDefaultProps,1");
    },
    getInitialState:function(){
        console.log("getInitialState,2");
        return null;
    },
    componentWillMount:function(){
        console.log("componmentWillMount,3");
    },
    render:function(){
      console.log("render,4");
      return <p ref = "childp">Hello{(function (obj){
              if (obj.props.name)
                return obj.props.name
              else
                return "World"
            })(this)} </p>;
    },
    componentDidMount:function(){
        console.log("componmentDidMount,5");
    },
});

React.render(<div style = {style}> <TextClass></TextClass> </div>,document.body);

运行阶段的函数

var style = {
  color : "red",
  border : "1px #000 solid",
};

var TextClass = React.createClass({
    componentWillReceiveProps:function(newProps){
      console.log("componentWillReciveProps,1");
      console.log(newProps);
    },
    shouldComponentUpdate:function(){
      console.log("shouldComponentUdate,2");return true;
    },
    componentWillUpdate:function(){
      console.log("componentWillUpdate,3");
    },
    render:function(){
      console.log("render,4");
      return <p>hello:{this.props.name ? this.props.name : "world!"}</p>;
    },
    componentDidUpdate:function(){
      console.log("componentDidUpadate,5");
    },
});
var TextSourceClass = React.createClass({
  getInitialState:function(){
    return {name :''};
  },
  handleChange:function(event){
    this.setState({name : event.target.value});
  },
  render:function(){
    return <div>
      <TextClass name = {this.state.name}></TextClass>
      <br/><input type="text"onChange = {this.handleChange}/>
    </div>;
  },
});

React.render(<div style = {style}> <TextSourceClass></TextSourceClass> </div>,document.body);

销毁阶段

var style = {
  color : "red",
  border : "1px #000 solid",
};

var TextClass = React.createClass({

    render:function(){
      console.log("render,4");
      return <p>hello:{this.props.name ? this.props.name : "world!"}</p>;
    },
    componentDidUpdate:function(){
      console.log("componentDidUpadate,5");
    },
});
var TextSourceClass = React.createClass({
  getInitialState:function(){
    return {name :''};
  },
  handleChange:function(event){
    this.setState({name : event.target.value});
  },
  render:function(){
    if(this.state.name == "1"){
      return <div>123</div>;
    }
    return <div>
        <TextClass name = {this.state.name}></TextClass>
        <br/><input type="text"onChange = {this.handleChange}/>
      </div>;
  },
});

React.render(<div style = {style}> <TextSourceClass></TextSourceClass> </div>,document.body);
posted @ 2016-08-12 11:58  晴明桑  阅读(427)  评论(0编辑  收藏  举报