麻烦老师帮忙看下关于双向绑定这一块我的理解对吗

来源:4-8 派发更新(下)

慕丝1474250

2021-05-15

vue在初始化的时候,在beforeCreated和created之间按顺序进行初始化响应式数据,包括props,methods,data,computed,watch,在初始化data的过程中会调用observer方法来绑定数据劫持判断是否已经有了ob属性并且ob属性是observer对象实例有了就直接返回,不然就new一个observer实例,在new实例的时候会先定义一个不可枚举的ob属性,判断是否为数组,数组的话则进行遍历数组的内容调用observer方法,对象则遍历每一个属性调用defineReactive方法将属性变成响应式属性,在渲染的时候触发数据绑定的getter方法,判断当前是否存在渲染watcher,存在则添加订阅的watcher,在添加watcher则会先判断是否已经存在watcher然后再添加进dep,在当前渲染watcher结束时,会判断是否之前保存的watcher是否还在本轮的订阅数组中,如果不在则将其移出,以节约性能,避免修改一个当前不需要渲染的数据时也触发了渲染,在修改数据的时候触发绑定setter方法,在做一些判断值是否相同之后,如果新值为一个对象的话,则调用observer方法进行数据绑定,然后调用dep.notify方法通知watcher,notify方法里面会遍历之前收集的watcher,然后调用queueWatcher方法将他们添加进执行队列当中,会先判断当前watcher是否已经在队列中,如果在队列中则跳过,如果不在则添加进队列中,然后通过nextTick调用flushSchedulerQueue方法(这里开发环境下是直接调用的,应该是考虑到节约性能,所以将本次同步任务中的修改渲染watcher一起放到微任务中执行),在flushSchedulerQueue方法中会将队列中的watcher进行排序,id小的先执行,1.以让父组件先于子组件渲染,2.userwatcher先于renderwatcher执行因为父组件和userwathcer先创建,3.如果父组件渲染执行中销毁了子组件,则可以跳过该子组件的渲染。然后调用run方法,触发getter方法计算值,如果是userwatcher则调用回调函数,如果是渲染watcher则会将当前渲染watcher添加进栈,然后再触发watcher的getter回调函数,也就是传入updateComponent进行更新视图,然后将当前watcher移除出栈,并清理订阅(因为在本次渲染中又会触发数据的getter函数重新进行订阅)

写回答

1回答

ustbhuangyi

2021-05-15

基本上理解问题不大,但你的所有分析是响应式原理,并非数据的双向绑定,你分析的过程也只包括了数据变化引起视图变化(触发 render watcher 的 update)的过程,并没有视图变化引起数据变化的过程。

另外你说的在开发环境同步执行 flushSchedulerQueue,跟你说的原因关系不大,详情看这次提交 https://github.com/vuejs/vue/pull/8240,主要是给测试用的。

0
1
慕丝1474250
非常感谢!
2021-05-15
共1条回复

Vue.js 源码深入解析 深入理解Vue实现原理

全方位讲解 Vue.js 源码,进阶高级工程师

4984 学习 · 1037 问题

查看课程