ReactJS组件生命周期详述

前面已经写了一篇关于reactJS组件生命周期的博文,此篇博文是一个补充,增加了一些例子,有助于更好的理解reactJS组件。 
初始化阶段能够使用的钩子函数(按照触发顺序): 
getDefaultProps(获取实例的默认属性)————只有第一次实例的时候调用,实例之间共享引用(属性) 
getInitialState(获取实例的初始状态)————初始化每个实例特有的状态 
必须返回一个Object或者是Null 
componentWillMount(组件即将被渲染到页面)——render之前最后一次修改状态的机会 
render(组件在render中生成虚拟的DOM节点,即JSX,最后由React生成真实的DOM节点)——只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。 
如果render需要修改状态和DOM输出,那么render就不能在服务端使用。并且,如果在render中修改状态和DOM输出,会使得代码逻辑变得复杂。所以,要尽可能避免这样做。 
componentDidMount(组件被渲染到页面之后)——成功render并渲染完成真实DOM之后触发,可以修改DOM

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="Keywords" content="关键词一,关键词二">
    <meta name="Description" content="网站描述内容">
    <meta name="Author" content="刘艳">
    <title></title>
</head>
<body>
    <div id = "example"></div>
    <div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
    var MyComponent = React.createClass({
        getDefaultProps: function(){
            console.log("获取实例的默认属性");
            return{name: "Yvette"};
        },
        getInitialState: function () {
            console.log("获取实例的初始状态");
            return{will:true};
        },
        componentWillMount: function () {
            console.log("组件即将被渲染到页面");
        },
        handleClick: function(event){
            this.setState({will: !this.state.will});
        },
        componentDidMount: function(){
            console.log("aaaa");
            if(this.state.will){
                $(this.refs.example).append("啦啦啦");
            }else{
                $(this.refs.example).append("郁闷");
            }
        },
        render: function(){
            console.log("render");
            return(
                <div>
                <p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
            </div>
            )
        }
    });
    ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
    ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>

 
从运行结果可以看出: 
1、获取默认属性(getDefaultProps)只会在第一次实例化组件时运行一次,后面不会再运行, 
2、获取初始状态(getInitialState)和componentWillMount,render,componentDidMount在每次实例化组件时,都会进入. 
3、点击切换时,只会触发render函数,因此我们写在componentDidMount函数中的状态判断不会再被执行.

运行中阶段能够使用的钩子函数(按照触发顺序): 
componentWillReceiveProps(组件快要接收到属性时触发)——父组件修改属性触发,可以修改新属性、修改状态。 
在修改发生之前出发。在属性真正比传送到组件之前,对其进行处理。 
shouldComponentUpdate(组件接收到新状态时,是否需要更新,返回false,React就不会更新,可以提高性能) 
componentWillUpdate(组件即将更新到页面)——不能修改属性和状态,会导致死循环 
render——只能访问this.props和this.state,不应再访问其它信息,只有一个顶层组件,但是可以有子组件,不允许修改状态和DOM输出。 
componentDidUpdate(在组件更新到页面之后调用)——可以修改DOM

<body>
    <div id = "example"></div>
    <div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
var MyComponent = React.createClass({
getDefaultProps: function(){
console.log("获取实例的默认属性");
return{name: "Yvette"};
        },
getInitialState: function () {
console.log("获取实例的初始状态");
return{will:true};
        },
componentWillMount: function () {
console.log("组件即将被渲染到页面");
        },
handleClick: function(event){
this.setState({will: !this.state.will});
        },
componentDidMount: function(){
console.log("组件被渲染到页面之后");
$(this.refs.example).append("啦啦啦");
        },
render: function(){
console.log("render")
return(
<div>
                    <p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
                </div>
);
        },
componentWillReceiveProps: function(){
console.log("组件快要接收到属性");
        },
shouldComponentUpdate: function(){
console.log("是否需要更新");
return false;
        },
componentWillUpdate: function(){
console.log("组件即将被更新");
        },
componentDidUpdate: function(){
console.log("组件更新被渲染到页面");
        }
    });
ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>

运行结果如下: 
 
从运行结果可以看出: 
1、在运行过程中,组件的状态发生改变时,首先进入shouldComponentUpdate函数,即组件是否需要更新,如果返回false,表示无需更新,直接返回。

<body>
    <div id = "example"></div>
    <div id = "example2"></div>
</body>
</html>
<script src="build/jquery-1.11.2.min.js"></script>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
    var MyComponent = React.createClass({
        getDefaultProps: function(){
            console.log("获取实例的默认属性");
            return{name: "Yvette"};
        },
        getInitialState: function () {
            console.log("获取实例的初始状态");
            return{will:true};
        },
        componentWillMount: function () {
            console.log("组件即将被渲染到页面");
        },
        handleClick: function(event){
            this.setState({will: !this.state.will});
        },
        componentDidMount: function(){
            console.log("组件被渲染到页面之后");
            //$(this.refs.example).append("啦啦啦");
        },
        render: function(){
            console.log("render")
            return(
                <div>
                    <p ref = "example" onClick = {this.handleClick}>{this.props.name}未来{this.state.will ? "会" : "不会"}更好!</p>
                    <span ref = "more">啦啦啦</span>
                </div>
            );
        },
        componentWillReceiveProps: function(){
            console.log("组件快要接收到属性");
        },
        shouldComponentUpdate: function(){
            console.log("是否需要更新");
            return true;
        },
        componentWillUpdate: function(){
            console.log("组件即将被更新");
            $(this.refs.example).css({"background": "#ccc","line-height":"30px"});
            //this.setState({will: !this.state.will});//导致一个死循环
        },
        componentDidUpdate: function(){
            console.log("组件更新被渲染到页面");
            if(this.state.will){
                $(this.refs.more).html("啦啦啦");
            }
            else{
                $(this.refs.more).html("郁闷");
            }
        }
    });
    ReactDOM.render(<MyComponent/>,document.querySelector("#example"));
    ReactDOM.render(<MyComponent/>,document.querySelector("#example2"));
</script>

 
从运行结果可以看出钩子函数的触发顺序:

1、shouldComponentUpdate,必须返回true或false,如果返回false,直接返回,不会再触发后面的钩子函数。
2、componentWillUpdate和componentDidUpdate中都可以操作DOM元素,因为当前在运行过程中,组件已经被渲染到了页面。但是最后是在componentDidUpdate中进行修改。

销毁中阶段能够使用的钩子函数(按照触发顺序): 
componentWillUnmount(在销毁操作执行之前触发)——在组件真正被销毁前调用,在删除组件之前进行清理操作,如计时器和事件监听器。

<body>
    <div id = "example"></div>
</body>
</html>
<script src="build/react.js"></script>
<script src="build/react-dom.js"></script>
<script src="build/browser.min.js"></script>
<script type="text/babel">
    var style = {
        color: "red",
        border: "1px solid #000"
    };
    var HelloWorld = React.createClass({
        render: function(){
            return <p>Hello, {this.props.name ? this.props.name : "World"}</p>;
        },
        componentWillUnmount: function(){
            console.log("I will unmount");
        }
    });
    var HelloUniverse = React.createClass({
        getInitialState: function(){
            return {name: "Yvette"};
        },
        handleChange: function (event) {
            if(event.target.value == "123"){
                React.unmountComponentAtNode(document.querySelector("#example"))
                return;
            }
            this.setState({name: event.target.value});
        },
        render: function(){
            return(
                <div>
                    <HelloWorld name = {this.state.name}></HelloWorld>
                    <br/>
                    <input type = "text" onChange = {this.handleChange} />
                </div>
            );
        }
    });
    ReactDOM.render(<div style = {style}><HelloUniverse></HelloUniverse></div>,document.querySelector("#example"));
</script>

当输入结果为123时,触发componentWillUnmount钩子函数。

文章导航