function scheduleWork(fiber, expirationTime) { // 获取根 node var root = scheduleWorkToRoot(fiber, expirationTime); null !== root && (!isWorking && 0 !== nextRenderExpirationTime && expirationTime < nextRenderExpirationTime && ((interruptedBy = fiber), resetStack()), markPendingPriorityLevel(root, expirationTime), (isWorking && !isCommitting$1 && nextRoot === root) || requestWork(root, root.expirationTime), nestedUpdateCount > NESTED_UPDATE_LIMIT && ((nestedUpdateCount = 0), reactProdInvariant("185"))); } function requestWork(root, expirationTime) { // 将需要渲染的root进行记录 addRootToSchedule(root, expirationTime); if (isRendering) { // Prevent reentrancy. Remaining work will be scheduled at the end of // the currently rendering batch. return; } if (isBatchingUpdates) { // Flush work at the end of the batch. if (isUnbatchingUpdates) { // ...unless we're inside unbatchedUpdates, in which case we should // flush it now. nextFlushedRoot = root; nextFlushedExpirationTime = Sync; performWorkOnRoot(root, Sync, true); } // 执行到这边直接return,此时setState()这个过程已经结束 return; } // TODO: Get rid of Sync and use current time? if (expirationTime === Sync) { performSyncWork(); } else { scheduleCallbackWithExpirationTime(root, expirationTime); } }
太过复杂,一些方法其实还没有看懂,但是根据断点可以把执行顺序先理一下,在 setState 之后会执行 performSyncWork ,随后是如下的一个执行顺序
performSyncWork => performWorkOnRoot => renderRoot => workLoop => performUnitOfWork => beginWork => applyDerivedStateFromProps
最终方法是执行
function applyDerivedStateFromProps( workInProgress, ctor, getDerivedStateFromProps, nextProps ) { var prevState = workInProgress.memoizedState; { if (debugRenderPhaseSideEffects || debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) { // Invoke the function an extra time to help detect side-effects. getDerivedStateFromProps(nextProps, prevState); } } // 获取改变的state var partialState = getDerivedStateFromProps(nextProps, prevState); { // 对一些错误格式进行警告 warnOnUndefinedDerivedState(ctor, partialState); } // Merge the partial state and the previous state. // 判断getDerivedStateFromProps返回的格式是否为空,如果不为空则将由原的state和它的返回值合并 var memoizedState = partialState === null || partialState === undefined ? prevState : _assign({}, prevState, partialState); // 设置state // 一旦更新队列为空,将派生状态保留在基础状态当中 workInProgress.memoizedState = memoizedState; // Once the update queue is empty, persist the derived state onto the // base state. var updateQueue = workInProgress.updateQueue; if (updateQueue !== null && workInProgress.expirationTime === NoWork) { updateQueue.baseState = memoizedState; } }
Vue
vue监听变量变化依靠的是 watch ,因此我们先从源码中看看, watch 是在哪里触发的。
Watch触发条件
在 src/core/instance 中有 initState()
/core/instance/state.js
在数据初始化时 initData() ,会将每vue的data注册到 objerserver 中
function initData (vm: Component) { // ...省略部分代码 // observe data observe(data, true /* asRootData */) } /** * Attempt to create an observer instance for a value, * returns the new observer if successfully observed, * or the existing observer if the value already has one. */ export function observe (value: any, asRootData: ?boolean): Observer | void { if (!isObject(value) || value instanceof VNode) { return } let ob: Observer | void if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { ob = value.__ob__ } else if ( shouldObserve && !isServerRendering() && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue ) { // 创建observer ob = new Observer(value) } if (asRootData && ob) { ob.vmCount++ } return ob }
来看下 observer 的构造方法,不管是array还是obj,他们最终都会调用的是 this.walk()
constructor (value: any) { this.value = value this.dep = new Dep() this.vmCount = 0 def(value, '__ob__', this) if (Array.isArray(value)) { const augment = hasProto ? protoAugment : copyAugment augment(value, arrayMethods, arrayKeys) // 遍历array中的每个值,然后调用walk this.observeArray(value) } else { this.walk(value) } }
我们再来看下walk方法,walk方法就是将object中的执行 defineReactive() 方法,而这个方法实际就是改写 set 和 get 方法