探索 MobX 的组件刷新机制:以函数组件为例
在 React 中,状态驱动视图是一切的核心。MobX 作为一个响应式状态管理库,以其优雅的响应式编程模型和自动化的依赖追踪机制,被广泛应用于中大型前端项目中。
本文将通过一个简单的函数组件例子,深入探讨 MobX 是如何做到 自动追踪依赖并触发组件刷新 的。
一、案例代码分析
我们从一个简单的 MobX + React 函数组件的例子出发:
1. Store 层(状态源)
import { makeObservable, observable, action } from "mobx";
class CounterStore {
count = 0;
constructor() {
makeObservable(this, {
count: observable,
increment: action,
});
}
increment() {
this.count++;
}
}
const counterStore = new CounterStore();
export default counterStore;
2. UI 层(函数组件)
import React from "react";
import { Observer, inject } from "mobx-react";
const App = inject("counterStore")((props) => {
const { counterStore } = props;
return (
<Observer>
{() => (
<div>
<h1>Count: {counterStore.count}</h1>
<button onClick={() => counterStore.increment()}>增加</button>
</div>
)}
</Observer>
);
});
export default App;
你会发现:每点击一次按钮,count
会加 1,页面也会自动刷新。MobX 是如何做到这一点的?
二、MobX 刷新机制的原理
1. observer 是入口
组件中的 Observer
或 observer()
(HOC)就是 MobX 监听依赖的入口。
在 mobx-react-lite
的源码中,observer(fn)
实际会包裹传入的组件,并通过 useObserver()
进行依赖追踪:
let observerComponent = (props, ref) => {
return useObserver(() => render(props, ref), baseComponentName)
}
2. useObserver 做了什么?
这是核心。我们来看下 useObserver
的关键部分:
const renderResult = reaction.track(() => {
renderResult = render(); // 执行组件的渲染逻辑
});
这一行做了两件事:
- 执行 render 函数(即组件渲染)
- 在执行过程中收集所有访问的 observable
为什么能“收集依赖”?这就涉及到 MobX 的底层响应系统了。
三、深入原理:MobX 如何做到自动刷新组件?
MobX 能自动刷新组件,靠的是 响应式系统 + 依赖追踪 + 渲染订阅,简单来说分为以下三步:
步骤 1:依赖收集(track)
MobX 对 observable 数据使用了 Proxy 代理,通过 get
方法拦截访问。当组件渲染时读取了 counterStore.count
,MobX 就知道这个组件依赖了这个数据。
这就叫 依赖收集(dependency tracking) 。
步骤 2:关系建立(subscribe)
每个组件在 observer()
包裹后,MobX 会为它创建一个 Reaction 实例。这个 Reaction 就是一个“副作用函数”,代表“当依赖变了,就要重新执行我”。
于是 MobX 会把这个 Reaction
挂到 counterStore.count
的依赖列表中,表示:
“当
count
被修改时,要通知这个 Reaction 重新执行。”
步骤 3:触发更新(reaction.run)
当你调用 counterStore.increment()
时,MobX 会通过 set
拦截到对 count
的赋值,然后通知它所有依赖的 Reaction
:
this.count++; // 触发 setter -> 通知依赖的 Reaction -> 执行组件的更新
在函数组件中,这一步会通过 React 的 useSyncExternalStore
API 去强制组件刷新。
四、架构类比总结
我们可以用下面的架构关系来理解 MobX:
组件 Observer
|
--> 创建 Reaction(响应函数)
|
--> 在渲染时 track(),记录访问的 observable
|
--> observable 属性注册 Reaction 为订阅者
|
当属性变化时 set() -> 通知 Reaction -> 强制刷新组件
一句话总结:
MobX 会在组件渲染时自动记录所访问的状态,并在这些状态变更时自动触发组件更新。
五、关键角色回顾
名称 | 作用 |
---|---|
observable | 将普通数据变成响应式数据(内部通过 Proxy 实现) |
reaction | 表示一个“副作用”,当依赖的数据变化时会重新执行 |
observer | 把组件变成响应式组件,会自动监听它内部访问的 observable |
track | 执行时收集依赖(被哪个 observable 读取了) |
useSyncExternalStore | React 18 中的底层 hook,用于响应式订阅并触发组件更新 |
六、写在最后
MobX 是一个非常优雅的响应式状态管理库,它的设计理念来自响应式编程,通过“自动依赖追踪 + 精准更新”的机制,让组件只在真正需要的时候才刷新,从而大大提升了性能。
理解 MobX 的更新机制,不仅能更好地使用它,也有助于你理解前端响应式编程模型的核心本质。