React类组件未调用生命周期方法为何能自动更新状态?
React类组件生命周期自动触发原理解析
以下是问题涉及的示例代码:
class Timer extends React.Component { constructor(props) { super(props); this.state = { seconds: 0 }; } tick() { this.setState(state => ({ seconds: state.seconds + 1 })); } componentDidMount() { this.interval = setInterval(() => this.tick(), 1000); } componentWillUnmount() { clearInterval(this.interval); } render() { return ( <div> Seconds: {this.state.seconds} </div> ); } } root.render(<Timer />);
代码中未手动调用componentDidMount但计时器正常运行、数值持续更新的原理,可从两个层面解释:
底层技术细节层面解释
- 当代码执行
root.render(<Timer />)时,React内部会启动类组件的完整挂载流水线:- 首先实例化
Timer组件类,调用constructor完成props绑定、初始state赋值 - 调用组件实例的
render()方法生成虚拟DOM树,将虚拟DOM转换为真实DOM节点,插入到页面对应的挂载容器中,完成首次渲染 - 挂载流程走到"真实DOM已插入页面"的节点时,React会主动检测当前组件实例是否定义了
componentDidMount方法——只要存在该方法,React就会绑定组件实例为this上下文,自动执行该方法,全程不需要业务代码手动调用
- 首先实例化
componentDidMount执行时,代码里的setInterval会被注册到浏览器的事件循环定时器线程,每隔1000ms就将tick回调推入宏任务队列;主线程空闲时回调执行,调用setState触发组件状态更新- 每次
setState触发后,React会重新调用render()生成新的虚拟DOM,和旧虚拟DOM做diff对比,将变化的seconds值更新到页面真实DOM上,因此页面数字会持续自增 - 当组件后续被从页面中移除时,React的卸载流水线同样会自动检测并执行实例上的
componentWillUnmount方法,清除定时器引用,避免内存泄漏
高层抽象通俗层面解释
你可以把React理解成一个全自动的快递驿站运营系统,写类组件就相当于给驿站写运营规则:
- 你不需要自己盯着时间喊"现在驿站开门了,赶紧开取件码短信机",也不需要自己喊"现在驿站关门了,赶紧关设备断电"
- 你只需要提前在规则里写清楚:开门后要做什么(对应
componentDidMount里开定时器)、关门前要做什么(对应componentWillUnmount里清定时器)、当前要给用户展示什么内容(对应render返回的页面结构)、初始的计数是多少(对应constructor里的初始state) - 系统会按照固定的运营流程,到点自动执行你提前写在对应规则里的内容:驿站开门(组件挂载到页面)的瞬间自动开计时器,每秒给计数加1,计数变了就自动更新对外显示屏的数字;等驿站关门(组件从页面卸载)的时候自动关掉计时器,不会一直空跑浪费资源。
你全程不需要手动调用这些对应节点的规则,系统自己会按流程触发。
内容的提问来源于stack exchange,提问作者ЯҽʋҽɳɠҽⲤⲀⲦ
相关产品推荐
相关产品推荐

