Vue双向绑定原理简析

一、原理

View的变化能实时让Model发生变化,而Model的变化也能实时更新到View

Vue采用数据劫持&发布-订阅的方式,通过ES5提供的Object.defineProperty()方法来劫持(监控)各属性的getter 、 seter ,并在数据(对象)发生变动时通知订阅者,触发相应的监听回调。并且,由于是在不同的数据上触发同步,可以精确的将变更发送给绑定的视图,而不是对所有的数据都执行一次检测。要实现 Vue 中的双向数据绑定,大致可以划分三个模块: Observer 、 compile 、 Watcher ,如图:

 

  • Observer 数据监听器,负责对数据对象的所有属性进行监听(数据劫持),监听到数据发生变化后通知订阅者。
  • compiler 指令解析器,扫描模板,并对指令进行解析,然后绑定指定事件。
  • Watcher 订阅者,关联 Observer 和 compile ,能够订阅并收到属性变动的通知,执行指令绑定的相应操作,更新视图。 Update ()是它自身的一个方法,用于执行compile 中绑定的回调,更新视图。

模板渲染解析时 watcher 会对应绑定指令(一对一)。

此时会通过调用订阅者 watcher 初始化( watcher 中 get() 方法)去触发对应属性在发布者 observer 里( object . defineProperty )的 getter , observer 会判断是不是通过 watcher 初始化调用的( Dep . target ,实例化之后会清空),只有是才会通过 dep 类依赖收集。
observer 通过 depend 通知 Dep 类收集( addDep 方法,在 watcher 类中,会传入当前 Dep 实例调用自身)当前该订阅者( watcher )中的触发更新的方法,同时第一次初始化 watcher . update ()初始化视图。此后每次的数据更新都会通过 observer 中的 setter 去触发 dep 类中的回调 update 执行收集依赖的所有方法更新订阅者中的状态同时更新视图。
observer 在处理对象和数组的时候,如果是数组,并且调用的方法会改变数组长度,则会重新增加索引之后更新数组,进行重新监听。(因为调用数组原生 AP 诃能多次触发 getter setter 且索引不会变),如果是对象则通过对象的 getter 获取值和 setter 更新值。

二、版本比较

vue 是基于依赖收集的双向绑定;3.0之前的版本使用 Object . defineProperty ,3.0新版使用Proxy


1、基于数据持/依赖收集的双向绑定的优点

  • 不需要显示的调用, Vue 利用数据劫持+发布订阅,可以直接通知变化并且驱动视图
  • 直接得到精确的变化数据,劫持了属性 setter ,当属性值改变我们可以精确的获取变化的内容 newVal ,不需要额外的 dif 操作

2、 object . defineProperty 的缺点

  • 不能监听数组;因为数组没有 getter 和 setter ,因为数组长度不确定,如果太长性能负担太大;
  • 只能监听属性,而不是整个对象;需要遍历属性;
  • 只能监听属性变化,不能监听属性的删减。

3、 proxy 好处

  • 可以监听数组;
  • 监听整个对象不是属性;
  • 13种拦截方法,强大很多;
  • 返回新对象而不是直接修改原对象,更符合 immutable ;

4、proxy 缺点

  • 兼容性不好,且无法用 polvfil 磨平:
posted @ 2022-03-17 22:20  木子末  阅读(347)  评论(0)    收藏  举报