mobx 原理解析
初始化:首先就是 mobx 在初始化的时候,是如何处理 observable 可观察属性的。 依赖收集:第二点就是通过 mobx-react 中的 observer ,如何收集依赖项,与 observable 建立起关系的。 派发更新:最后就是当改变可观察属性的值的时候,如何更新对应组件的。
依赖收集和依赖更新
function autorun(
view: (r: IReactionPublic) => any,
opts: IAutorunOptions = EMPTY_OBJECT
): IReactionDisposer {
const name: string = (opts && opts.name) || (view as any).name || "Autorun@" + getNextId()
const runSync = !opts.scheduler && !opts.delay
let reaction: Reaction
// 只看同步的autorun,异步是根据传入的delay setTimeout
if (runSync) {
// normal autorun
reaction = new Reaction(
name,
// reaction的onInvalidate, 用track调用reactionRunner, 也就是view(reaction), (重新)收集依赖
function(this: Reaction) {
this.track(reactionRunner)
},
opts.onError,
opts.requiresObservable
)
} else {
// ... 处理异步
}
function reactionRunner() {
view(reaction)
}
// 将 reaction 放进全局 globalState.pendingReactions 队列,里面会执行runReactions
reaction.schedule()
// 返回取消订阅
return reaction.getDisposer()
}
runReactions, runReactions 是依赖收集启动方法
let reactionScheduler (fn: () => void) => void = f => f();
function runReactions() {
// 不在事务中并且没有正在执行的reaction
if (globalState.inBatch > 0 || globalState.isRunningReactions) return
// 核心的调用runReactionsHelper
reactionScheduler(runReactionsHelper)
}
runReactionsHelper
function runReactionsHelper() {
globalState.isRunningReactions = true;
const allReactions = globalState.pendingReactions;
let iterations = 0;
// 遍历所有globalState.pendingReactions中的reaction,并执行每个对象的runReaction
while (allReactions.length > 0) {
if (++iterations === MAX_REACTION_ITERATIONS) {
console.error(
`Reaction doesn't converge to a stable state after ${MAX_REACTION_ITERATIONS} iterations.` +
` Probably there is a cycle in the reactive function: ${allReactions[0]}`
);
allReactions.splice(0); // clear reactions
}
let remainingReactions = allReactions.splice(0);
for (let i = 0, l = remainingReactions.length; i < l; i++)
remainingReactions[i].runReaction();
}
globalState.isRunningReactions = false;
}
provider 源码分析
var MobXProviderContext =
/*#__PURE__*/
React__default.createContext({});
function Provider(props) {
var children = props.children,
stores = _objectWithoutPropertiesLoose(props, ["children"]); // 获取除去children后的props对象
var parentValue = React__default.useContext(MobXProviderContext);
// `useRef`返回一个可变的 ref 对象,其`.current`属性被初始化为传入的参数(`initialValue`)。返回的 ref 对象在组件的整个生命周期内保持不变。
var mutableProviderRef = React__default.useRef(
_extends({}, parentValue, {}, stores)
);
var value = mutableProviderRef.current;
if (process.env.NODE_ENV !== "production") {
var newValue = _extends({}, value, {}, stores); // spread in previous state for the context based stores
if (!shallowEqual(value, newValue)) {
throw new Error(
"MobX Provider: The set of provided stores has changed. See: https://github.com/mobxjs/mobx-react#the-set-of-provided-stores-has-changed-error."
);
}
}
return React__default.createElement(
MobXProviderContext.Provider,
{
value: value,
},
children
);
}
Provider.displayName = "MobXProvider";
最后更新于
这有帮助吗?