We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
vue响应式的实现,包含了数据劫持、依赖收集、派发更新三部分,本章节单独讲解下派发更新
1、某一对象属性赋值,触发setter方法,setter方法做的几件事:
1、判断新旧值是否一样,如果一样,则结束函数,不一样往下执行 2、新值赋给旧值(val = newVal) 3、判断新值是否是个对象,如果是对象,则把该对象变成一个响应式的 4、执行dep.notify(),(派发更新的起点)
2、Dep.prototype.nitify() 的实现,它只做了两件事情
1、subs数组排序(从小到达排序,组件更新是父到子) 2、执行sub.update方法(循环遍历subs执行,sub指向的是一个watcher实例)
3、Watcher.prototype.update() 的实现
判断三种情况 1、this.lazy ->和计算属性相关,暂不介绍 2、this.sync -> 是否是同步执行的watcher,如果是,则立即执行this.run() 3、以上情况都不符合,执行queueWatcher方法,把当前watcher推入到一个queue中
4、queueWatcher() 的实现
4.1 判断当前watcher是否在缓存中
const id = watcher.id if (has[id] == null) { // ... }
这里 has是一个对象,存在于闭包中。 如果存在,则说明该watcher已经被push进队列了,啥也不用做; 如果不存在,则把该watcher push到一个数组中; (watcher Id相同的场景,一个组件内,同时修改了两个变量,而且这两个变量都会触发页面更新)
watcher
push
4.2 判断flushing, 如果没有,则直接把watcher 放进 queue数组中
flushing
queue
4.3 判断waiting 是否是false(waiting初始值为false),则把waiting = true,在没有执行resetSchedulerState前,nextTick方法只执行一次
waiting
false
waiting = true
resetSchedulerState
nextTick
if (!waiting) { waiting = true // ...... nextTick(flushSchedulerQueue) }
5、执行nextTick方法,nextTick方法执行timeFunc,返回一个Promise,代码如下
timeFunc
Promise
function nextTick(cb) { if (!pending) { pending = true timerFunc() } // 如果没有传cb,并Promise可用,则返回一个promise实例 if (!cb && typeof Promise !== 'undefined') { return new Promise(resolve => { _resolve = resolve }) } }
5.1 timerFunc是个懒函数,初始化的时候,只执行一次;它主要功能是判断使用哪种nextTick方案,分别判断promise、MutationObserver、setImmediate、setTimeout
timerFunc
promise
MutationObserver
setImmediate
setTimeout
6 flushSchedulerQueue方法的实现
flushSchedulerQueue
6.1 queue从小到大排序;排序的作用有:1、先更新父组件,后更新子组件;2、user watcher 先与 render watcher执行(因为user watcher先于render watcher创建);3、如果一个组件被销毁,父组件正在被执行 watcher run,当前watcher会被跳过
queue.sort((a, b) => a.id - b.id)
6.2循环遍历执行queue中的watcher
for(index = 0; index < queue.length; index ++) { watcher = queue[index] if (watcher.before) { watcher.before() } id = watcher.id has[id] = null watcher.run() }
6.3 执行resetSchedulerState方法
function resetSchedulerState () { index = queue.length = activatedChildren.length = 0 has = {} if (process.env.NODE_ENV !== 'production') { circular = {} } waiting = flushing = false }
总结:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
1、某一对象属性赋值,触发setter方法,setter方法做的几件事:
2、Dep.prototype.nitify() 的实现,它只做了两件事情
3、Watcher.prototype.update() 的实现
4、queueWatcher() 的实现
4.1 判断当前watcher是否在缓存中
这里 has是一个对象,存在于闭包中。
如果存在,则说明该
watcher
已经被push
进队列了,啥也不用做;如果不存在,则把该
watcher
push到一个数组中;(watcher Id相同的场景,一个组件内,同时修改了两个变量,而且这两个变量都会触发页面更新)
4.2 判断
flushing
, 如果没有,则直接把watcher
放进queue
数组中4.3 判断
waiting
是否是false
(waiting初始值为false),则把waiting = true
,在没有执行resetSchedulerState
前,nextTick
方法只执行一次5、执行
nextTick
方法,nextTick
方法执行timeFunc
,返回一个Promise
,代码如下5.1
timerFunc
是个懒函数,初始化的时候,只执行一次;它主要功能是判断使用哪种nextTick
方案,分别判断promise
、MutationObserver
、setImmediate
、setTimeout
6
flushSchedulerQueue
方法的实现6.1
queue
从小到大排序;排序的作用有:1、先更新父组件,后更新子组件;2、user watcher 先与 render watcher执行(因为user watcher先于render watcher创建);3、如果一个组件被销毁,父组件正在被执行 watcher run,当前watcher会被跳过6.2循环遍历执行
queue
中的watcher
6.3 执行
resetSchedulerState
方法总结:
The text was updated successfully, but these errors were encountered: