vue双向绑定核心
数据劫持+发布订阅模式。
数据劫持
数据劫持的核心是Object.defineProperty()。
1 | descriptor = { |
vue双向绑定主要组成部分
- Ovserver:主要的工作是递归地监听对象上的所有属性,在属性的值改变时,触发相应的watcher。
- Watcher:观察者。当监听的数据(触发set)修改时,执行相应的回调函数。(调用compiler更新模板)
- Dep:连接Observer和Watcher的桥梁,每一个Observer对应一个Dep,它内部维护一个数组,保存于该Observer相关的Watcher(当使用该值时,会把使用者存放到该Observer的Dep对象中)。
- Compiler:模板解析器,用于渲染数据。
一个简单的demo
Observer
1 | function Observer(obj,key,value) { |
Dep
1 | function Dep(){ |
Watcher
1 | //fn是数据变化后腰执行的回调函数,一般是获取数据渲染模板 |
同一时刻只有一个watcher处于激活状态,把当前watcher绑定在Dep.target(方便在Observer内获取)。回调结束后,销毁Dep.target。
html
1 |
|
总结Vue双向绑定实现
- Vue会为data中对象(处理Object [walk函数] 和Array [observeArray函数])的每个属性通过
Object.defineProperty()
添加一个get、set属性,将每个属性设置为可观察的(Observer),每个属性内部维护一个dep数组,这个数组存放着与这个属性有关的watcher对象,watcher对象可以理解为使用了某个observer属性的对象。 - 使用Observer属性时会触发该属性的get函数。调用get函数时,表示该属性被使用,这时就会调用dep.addsubs()把当前的watcher存放到当前observer属性的dep数组中。
- 修改Observer属性时会触发该属性的set函数。调用set时,会遍历当前Ovserver的dep数组中的watcher,调用dep.notify()通知watcher修改vdom对象,修改完成之后更新模板。
虚拟dom
虚拟dom对应的就是真实dom。虚拟dom是真实dom的抽象化,是对象。
当我们页面中dom数比较多的时候,频繁的修改、增加dom的数量,对性能会有极大的浪费。虚拟dom就是为了解决这个问题而生,它建立在真实的dom之上。当数据驱动dom修改时,它会通过diff计算,来尽量少的创建新元素,而尽可能多地复用旧的om,这样就可以减少频繁创建新dom带来的消耗。