vue实现数据双向绑定MVVM原理

vue实现数据双向绑定主要是:

  • 采用 数据劫持 结合 发布者-订阅者模式 的方式,数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变
  • 核心( Vue2.0 ):通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。

在这里插入图片描述

  1. 数据监听器 Observer
  2. 指令解析器 Compile
  3. 订阅者 Watcher
  4. 消息订阅器 Dep

  • Observer 数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  • 利用Obeject.defineProperty()来监听属性变动 那么将需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 settergetter 这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化。 (PS: 当某个属性被访问时,则会调用getter方法,当data中的属性被改变时,则会调用setter方法。)
  • 这样我们已经可以监听每个数据的变化了,那么监听到变化之后就是怎么通知订阅者了,所以接下来我们需要实现一个消息订阅器
  • Dep 消息订阅器,内部维护了一个数组,用来收集订阅者(Watcher),数据变动触发notify 函数,再调用订阅者的 update 方法。
  • Dep 用于储存订阅者并发布消息

  • Compile 主要做的事情是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图,如图所示:
    在这里插入图片描述

  • Watcher 订阅者,作为连接 Observer 和 Compile 的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数, 从而更新视图
    • 在自身实例化时往属性订阅器(dep)里面添加自己
    • 自身必须有一个update()方法
    • 待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

  • MVVM 作为数据绑定的入口,整合ObserverCompileWatcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起ObserverCompile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。

为什么Vue3.0不再使用defineProperty实现数据监听

3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:

  1. 只能监测属性,不能监测对象
  2. 检测属性的添加和删除;
  3. 检测数组索引和长度的变更;
  4. 支持 Map、Set、WeakMap 和 WeakSet。

  • Object.defineProperty 真的无法监测数组下标的变化吗

  Object.defineProperty 对数组和对象的表现一致,并非不能监控数组下标的变化,vue2.x中无法通过数组索引来实现响应式数据的自动更新是vue本身的设计导致的,不是 defineProperty 的锅.

  • 对比Object.defineProperty和 Proxy
  1. Object.defineProperty只能劫持对象的属性,而Proxy是直接代理对象。
      由于 Object.defineProperty 只能对属性进行劫持,需要遍历对象的每个属性,如果属性值也是对象,则需要深度遍历。而 Proxy 直接代理对象,不需要遍历操作。
  2. Object.defineProperty对新增属性需要手动进行Observe
  3. 由于 Object.defineProperty 劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持。也正是因为这个原因,使用vue给 data 中的数组或对象新增属性时,需要使用 vm.$set 才能保证新增的属性也是响应式的。
  4. Proxy支持13种拦截操作,这是defineProperty所不具有的
  5. 新标准性能红利 Proxy 作为新标准,长远来看,JS引擎会继续优化 Proxy ,但 gettersetter 基本不会再有针对性优化。
  6. Proxy兼容性差

总结:

  • Object.defineProperty 对数组和对象的表现一直,并非不能监控数组下标的变化,vue2.x中无法通过数组索引来实现响应式数据的自动更新是vue本身的设计导致的,不是 defineProperty 的锅。
  • Object.definePropertyProxy 本质差别是,defineProperty 只能对属性进行劫持,所以出现了需要递归遍历,新增属性需要手动 Observe 的问题。
  • Proxy 作为新标准,浏览器厂商势必会对其进行持续优化,但它的兼容性也是块硬伤,并且目前还没有完整的polifill方案。

分析 Vue2.x 中对数组 Observe 部分源码

分析 Vue2.x 中对数组 Compile部分源码

分析 Vue2.x 中对数组 Compile部分源码

关于Object.defineProperty来实现观察者机制,可以参照剖析Vue原理&实现双向绑定MVVM这篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值