前面已经写了一篇关于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钩子函数。