React 初学者:组件的生命周期
生命周期方法我觉得是很复杂。我们可以把它们当作是在组件生命中的不同的点被调用的美化的事件处理器,并且就像事件处理器一样,我们可以在这些不同的点编写代码做一些事情。在深入之前,我们先来快速了解一下生命周期方法。它们是 componentWillMount, componentDidMount, componentWillUnmount, componentWillUpdate, componentDidUpdate, shouldComponentUpdate, componentWillReceiveProps。 还有三个方法严格上讲并非生命周期方法,但是我们仍要把它们跟生命周期方法混在一起,它们是 getInitialState、getDefaultProps 和 render。
这些方法中,有些名称可能看起来是熟悉,有些可能是第一次看到。不要着急。在本教程结束后,你对所有这些方法都很熟悉。我们打算要做的是从不同角度看看这些生命周期方法。我们还是以代码开始!
1.demo研究
首先看一个关于react组件生命周期的demo,记录了组件的生老病死
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Hello React!</title>
<script src="https://fb.me/react-15.0.0-rc.2.js"></script>
<script src="https://fb.me/react-dom-15.0.0-rc.2.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var Counter = React.createClass({
render: function () {
var textStyle = {
fontSize: 72,
fontFamily: "sans-serif",
color: "#333",
fontWeight: "bold"
};
return (
<div style={textStyle}>
{this.props.display}
</div>
);
}
});
var destination = document.querySelector("#container");
var CounterParent = React.createClass({
getDefaultProps: function () {
console.log("getDefaultProps: Default prop time!");
return {};
},
getInitialState: function () {
console.log("getInitialState: Default state time!");
return {
count: 0
};
},
increase: function () {
this.setState({
count: this.state.count + 1
});
},
componentWillUpdate: function (newProps, newState) {
console.log("componentWillUpdate: Component is about to update!");
},
componentDidUpdate: function (currentProps, currentState) {
console.log("componentDidUpdate: Component just updated!");
},
componentWillMount: function () {
console.log("componentWillMount: Component is about to mount!");
},
componentDidMount: function () {
console.log("componentDidMount: Component just mounted!");
},
componentWillUnmount: function () {
console.log("componentWillUnmount: Component is about to be removed from the DOM!");
},
shouldComponentUpdate: function (newProps, newState) {
console.log("shouldComponentUpdate: Should component update?");
if (newState.count < 5) {
console.log("shouldComponentUpdate: Component should update!");
return true;
} else {
ReactDOM.unmountComponentAtNode(destination);
console.log("shouldComponentUpdate: Component should not update!");
return false;
}
},
componentWillReceiveProps: function (newProps) {
console.log("componentWillReceiveProps: Component will get new props!");
},
render: function () {
var backgroundStyle = {
padding: 50,
border: "#333 2px dotted",
width: 250,
height: 100,
borderRadius: 10,
textAlign: "center"
};
return (
<div style={backgroundStyle}>
<Counter display={this.state.count}/>
<button onClick={this.increase}>
+
</button>
</div>
);
}
});
ReactDOM.render(
<div>
<CounterParent />
</div>,
destination
);
</script>
</body>
</html>
点击demo查看运行结果,当页面加载时,你会看到一个简单的计数器示例:
先不要点击按钮或者任何东西。如果已经点击了按钮,那就重新刷新一下页面,让示例重新开始。
现在打开浏览器的开发功能根据,看看 Console 标签。在 Chrome 中,我们会看到如下的东西:
注意一下打印的东西。你会看到一些消息,这些消息的开头看起来像生命周期方法的名字。如果现在你点击加号按钮,会看到 Console 会显示更多被调用的生命周期方法:
玩这个示例一会儿。这个示例所做的是,允许你把所有这些生命周期方法放在我们前面已经看到的组件上下文中。随着你继续点击加号按钮,更多的生命周期方法条目就会打印出来。最后,当计数器到了 5 时,示例消失,控制台输出如下条目:componentWillUnmout: Component is about to be removed from the DOM!。 此时,示例结束。
我们需要自己花点时间理解一下这段代码做什么。这段代码看起来有点长,但是只是列出定义有 console.log 语句的每个生命周期方法。看完代码后,多玩几次。相信我,你在这个示例上花的时间越多,思考发生了什么,就会觉得越有意思。下面的小节我们会看每个生命周期方法中的渲染、更新和卸载阶段,虽然很枯燥,但是还是要自己取理解,去研究.
2.初始渲染阶段
当组件准备开始其生命,进入 DOM 时,如下的生命周期方法被调用
当示例被加载时,你在控制台看到的,就是这里看到的无彩色的版本。现在我们继续深入学习每个生命周期方法:
getDefaultProps:该方法允许我们指定 this.props 的默认值。它在组件被创建或者父组件的任何属性传递进来之前被调用。
getInitialState:本方法允许我们指定在组件被创建前 this.state的默认值。与 getDefaultProps 方法一样,它也是在组件被创建前被调用。
componentWillMount:这是组件被渲染到 DOM 之前被调用的最后一个方法。一个需要指出的重要事情是:如果在这个方法中调用 setState,那么组件是不会被重新渲染。
render:这个方法对于我们来说肯定很熟悉。每个组件必须定义有这个方法,它负责返回单个根 HTML 节点(该节点内部可以有很多字节点)。如果我们不想渲染任何东西,让它返回 null 或者 false 即可。
componentDidMount:组件渲染并且放到 DOM 后,该方法会立即被调用。在这个点上,我们可以安全的执行任何 DOM 查询操作,而不用担心组件是否被创建。如果有代码依赖于组件是否准备好了,那么你也可以在这里指定所有代码。
除了 render 方法外,所有这些生命周期方法只能触发一次。这与我们下面要看到的方法有很大不同。
3.更新阶段
在组件添加到 DOM 之后,当属性或者状态发生更改时,组件可能会更新。在此期间,会有一些生命周期方法被调用。
处理状态改变
首先,我们来看看状态改变。当状态改变发生时,前面我们提到组件会再次调用其 render 方法。任何依赖于该组件的输出的组件的 render 方法也会被调用。这样做就可以确保组件总是显示最新版本的自己。这一切都是真的,但是这只是对发生的事情的部分表示。
当状态发生改变时,如下生命周期方法被调用:
shouldComponentUpdate 有时,当一个状态发生改变时,你不想让组件更新。这个方法可以让我们控制更新行为。如果你使用该方法,并返回一个 true 值,组件就会被更新。如果返回一个 false 值,该组件就不会更新。
componentWillUpdate 该方法在组件将要被更新之前被调用。这里没啥值得兴奋的。有一件事情要指出的是,不能在这个方法中通过调用 this.setState 来修改状态。
render 如果没有通过 shouldComponentUpdate 忽略更新,那么 render 中的代码会再次被调用,以确保组件正确显示自己。
componentDidUpdate 该方法在组件更新以及 render 方法被调用过后被调用。如果你要在更新发生后执行一些代码,那么就应该把代码放在这个方法中。
处理 prop 改变
组件更新的另一个时间是,当组件已经被渲染到 DOM 以后,其 prop 值发生改变时。在这种情况下,如下的生命周期方法被调用:
这里唯一的新方法是 componentWillReceiveProps。该方法只返回一个参数,并且该参数包含将要赋值的新 prop 值。
剩下的生命周期方法我们在前面查看状态改变时已经看过了,所以这里就不在重复了。在处理 prop 修改时,它们的行为是一致的。
4.卸载阶段
最后一个阶段是当组件要销毁,并从 DOM 中删除时:
这里唯一的生命周期方法是 componentWillUnmount。我们可以在这个方法中执行清理相关的任务,比如移除事件监听器、停止计数器等等。在该方法被调用后,组件就从 DOM 中移除,你可以对它说拜拜了。
5.自我总结
react的生命周期其实没有想象的那么难,但是如果自己不话费时间研究,只是一味的抱怨的话,那是永远不会理解的.其实组件的生命周期,就像人的一生,开始在妈妈肚子里面待着等待出生,然后成长,但是成长过程中会遇到很多变数需要自己去解决应对,这也会不断地让自己变得的成熟稳重,到了最后阶段人都会消失不见,化为尘埃飘去.