React源码解析(二):组件的类型与生命周期
2023-11-16 14:05:54
在上一篇文章《React源码解析(一):组件的实现与挂载》中,我们阐述了React组件的实现和挂载。现在我们来一起探究组件的生命周期。
我们已经知道,只有在挂载流程开始后,才会触发组件的生命周期,生成ReactElement类型的js对象,通过解析组件对象内部所携带的信息,获得组件的类型、props和children等信息,从而创建出对应的组件实例。
React组件的生命周期分为四个阶段:
-
初始化阶段
在这个阶段,React会创建组件实例,并调用组件的constructor方法。constructor方法中,我们可以初始化组件的状态和绑定事件处理函数。
-
挂载阶段
在这个阶段,React会将组件实例挂载到DOM中。挂载是指将组件实例渲染成HTML元素,并插入到指定的位置。在挂载阶段,React会调用组件的componentDidMount方法。componentDidMount方法中,我们可以执行一些初始化操作,比如发送网络请求或设置定时器。
-
更新阶段
当组件的状态或props发生变化时,React会触发组件的更新阶段。在更新阶段,React会调用组件的shouldComponentUpdate方法。shouldComponentUpdate方法中,我们可以决定是否需要更新组件。如果需要更新组件,React会调用组件的componentWillUpdate方法。componentWillUpdate方法中,我们可以执行一些更新前的操作,比如保存组件的状态。然后,React会调用组件的render方法,重新渲染组件。最后,React会调用组件的componentDidUpdate方法。componentDidUpdate方法中,我们可以执行一些更新后的操作,比如更新组件的DOM元素。
-
卸载阶段
当组件从DOM中卸载时,React会调用组件的componentWillUnmount方法。componentWillUnmount方法中,我们可以执行一些卸载操作,比如清除定时器或取消网络请求。
组件的生命周期如下图所示:
[初始化阶段] -> [挂载阶段] -> [更新阶段] -> [卸载阶段]
组件的生命周期对于理解React的工作原理非常重要。通过对组件生命周期的理解,我们可以更好地掌握React的组件化思想,并编写出更健壮的React应用程序。
接下来,我们将详细介绍每个生命周期阶段的具体内容。
初始化阶段
在初始化阶段,React会创建组件实例,并调用组件的constructor方法。constructor方法中,我们可以初始化组件的状态和绑定事件处理函数。
初始化组件实例
组件实例是组件在内存中的表示。它包含组件的状态、props和children等信息。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
this.handleClick = this.handleClick.bind(this);
}
// 其他方法
}
在上面的代码中,我们定义了一个名为MyComponent的组件。在组件的constructor方法中,我们初始化了组件的状态和绑定了事件处理函数handleClick。
初始化组件状态
组件的状态是一个对象,它包含组件内部的数据。组件的状态可以通过this.setState()方法进行更新。
this.setState({
count: this.state.count + 1
});
在上面的代码中,我们通过this.setState()方法将组件的状态count更新为count + 1。
绑定事件处理函数
事件处理函数是组件用来处理事件的方法。事件处理函数需要在constructor方法中绑定到组件实例上。
this.handleClick = this.handleClick.bind(this);
在上面的代码中,我们将事件处理函数handleClick绑定到了组件实例上。这样,当组件的DOM元素发生click事件时,就会调用组件的handleClick方法。
挂载阶段
在挂载阶段,React会将组件实例挂载到DOM中。挂载是指将组件实例渲染成HTML元素,并插入到指定的位置。在挂载阶段,React会调用组件的componentDidMount方法。
挂载组件实例
React会将组件实例挂载到DOM中。挂载是指将组件实例渲染成HTML元素,并插入到指定的位置。
ReactDOM.render(<MyComponent />, document.getElementById('root'));
在上面的代码中,我们将MyComponent组件实例挂载到了id为root的DOM元素中。
调用componentDidMount方法
在组件挂载完成后,React会调用组件的componentDidMount方法。componentDidMount方法中,我们可以执行一些初始化操作,比如发送网络请求或设置定时器。
componentDidMount() {
// 发送网络请求
fetch('https://example.com/api/data')
.then(response => response.json())
.then(data => {
this.setState({
data: data
});
});
// 设置定时器
this.timer = setInterval(() => {
this.setState({
count: this.state.count + 1
});
}, 1000);
}
在上面的代码中,我们在componentDidMount方法中发送了一个网络请求,并设置了一个定时器。
更新阶段
当组件的状态或props发生变化时,React会触发组件的更新阶段。在更新阶段,React会调用组件的shouldComponentUpdate方法。shouldComponentUpdate方法中,我们可以决定是否需要更新组件。如果需要更新组件,React会调用组件的componentWillUpdate方法。componentWillUpdate方法中,我们可以执行一些更新前的操作,比如保存组件的状态。然后,React会调用组件的render方法,重新渲染组件。最后,React会调用组件的componentDidUpdate方法。componentDidUpdate方法中,我们可以执行一些更新后的操作,比如更新组件的DOM元素。
触发更新阶段
组件的状态或props发生变化时,会触发组件的更新阶段。
this.setState({
count: this.state.count + 1
});
在上面的代码中,我们将组件的状态count更新为count + 1。这会触发组件的更新阶段。
调用shouldComponentUpdate方法
在组件的更新阶段,React会首先调用组件的shouldComponentUpdate方法。shouldComponentUpdate方法中,我们可以决定是否需要更新组件。
shouldComponentUpdate(nextProps, nextState) {
return this.state.count !== nextState.count;
}
在上面的代码中,我们判断组件的状态count是否发生变化。如果count发生变化,则返回true,表示需要更新组件。否则,返回false,表示不需要更新组件。
调用componentWillUpdate方法
如果shouldComponentUpdate方法返回true,React会调用组件的componentWillUpdate方法。componentWillUpdate方法中,我们可以执行一些更新前的操作,比如保存组件的状态。
componentWillUpdate(nextProps, nextState) {
this.prevCount = this.state.count;
}
在上面的代码中,我们在componentWillUpdate方法中保存了组件的状态count。
调用render方法
在调用componentWillUpdate方法之后,React会调用组件的render方法。render方法中,我们可以返回组件的UI结构。
render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.handleClick}>+</button>
</div>
);
}
在上面的代码中,我们返回了一个包含一个h1元素和一个button元素的UI结构。
调用componentDidUpdate方法
在调用render方法之后,React会调用组件的componentDidUpdate方法。componentDidUpdate方法中,我们可以执行一些更新后的操作,比如更新组件的DOM元素。
componentDidUpdate(prevProps, prevState) {
if (this.prevCount !== this.state.count) {
// 更新DOM元素
this.refs.count.innerHTML = this.state.count;
}
}
在上面的代码中,我们在componentDidUpdate方法中更新了DOM元素的innerHTML属性。
卸载阶段
当组件从DOM中卸载时,React会调用组件的componentWillUnmount方法。componentWillUnmount方法中,我们可以执行一些卸载操作,比如清除定时器或取消网络请求。
触发卸载阶段
当组件从DOM中卸载时,会触发组件的卸载阶段。
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
在上面的代码中,我们将MyComponent组件实例从DOM中卸载。
调用componentWillUnmount方法
在组件的卸载阶段,React会调用组件的componentWillUnmount方法。componentWillUnmount方法中,我们可以执行一些卸载操作,比如清除定时器或取消网络请求。
componentWillUnmount() {
// 清除定时器
clearInterval(this.timer