了解 Vue 源码是吗?简单说说它的响应式,我不想听八股文
前言
平时也没少看 Vue 源码相关的文章,但总是感觉一知半解。这不一到面试的时候,就开始结结巴巴,虽然能说到零星半点,但给面试官的感觉就是你这个人好像不太懂
。所以就简单的记录一下自己的一知半解,希望大家勘误
。
响应三兄弟
在我看来,Vue 的响应式主要是通过 Observer 类(监听者)
、Dep 类(管家)
、Watcher 类(订阅者)
三兄弟来配合完成的。接下来我们看看三兄弟分别是干啥的。
Observer
它就好像一个监控,通过 Object.defineProperty
来监控需要响应式的数据。那它是怎么进行监控的呢?主要是通过拦截 set
和 get
属性描述符。
-
get
: 当某些地方尝试获取属性值的时候,就会触发get
, 这个时候Observer
就会特别关注这个属性了,它会把全局唯一的watcher(先不管它是怎么来的)
交给自己的管家Dep(每个属性都有一个自己的管家)
,然后管家就会把 watcher 收集起来以便后续的操作。 -
set
:当某些地方尝试给属性赋值的时候,就会触发set
。这个时候Observer
又来了,它会通知自己的管家Dep
,该干活了,这时候Dep
就会通知自己收集的那些Watcher
去干自己该干的事。
Dep
它就是一个管家,好好看着自己的属性就行了。所以对象的每一个属性都会有一个 Dep
,它内部维护着一个数组,用来存储 Watcher
。同时它也需要在合适的时候去督促 watcher 们干活。
Watcher
它实际上是响应式的实际执行者(可能这么说欠妥
)。因为响应式的完成是在它这里执行的,它这里存放着很多的回调。那它又是怎么来的呢?
在页面初次渲染的时候啊,一旦见到了 {{/../}}、v-model、v-bind、computed、watch
这些奇形怪状的玩意,都会生成一个 Watcher
的实例。与此同时呢,当前的管家 Dep
会有一个 target
属性指向这个 watcher
实例。不过一旦这个实例被管家收集了,管家就会释放 target
,换下一个 watcher
来收集。
兄弟齐心,其利断金
总的来说,就是在我们 new
一个 vue
实例的时候,首先会进行数据的响应式处理。这个时候 Observer
开始干活,它开始递归的遍历对象每一个属性,生成对应的管家 Dep,并且监听到属性对应的 set
和 get
。
在初次渲染的时候,会根据不同的情况生成不同的 watcher 实例
。当尝试获取属性值的时候,就会触发 get
,那么此时属性的管家就会收集这个 watcher
实例。当尝试给属性赋值的时候,就会触发 set
,此时管家又会出来干活了,它会通知收集的 watcher
执行自己的回调,例如更新页面。
总结
个人的片面理解存在偏颇之处,希望大家不吝赐教。
转载自:https://juejin.cn/post/7296672743616151602