VUE2中的双向绑定原理
Vue2.0的数据响应是采用数据劫持结合发布者—订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter、getter。
缺陷:
- vue实例创建后,无法检测到对象属性的新增或删除,只能追踪到数据是否被修改(Object.defineProperty只能劫持对象的属性)。
当创建一个Vue实例时,将遍历的所有Dom对象,并为每个数据属性添加setter和getter回调。这两个回调允许观察数据的更改并触发更新,但是若对Dom对象的操作是在Vue实例化之后,这个数据将不会被vue捕捉到,因此也无法实现响应。
解决方案:
Vue.set(obj, propertName/index, value)
// vue中set方法会给对象设置一个响应式属性,第一个参数为需要修改的对象,第二个参数是要添加的属性,第三个参数是属性的值。
data.location = {
x: 100,
y: 100
}
data.location = {...data, z: 100}
- 不能监听到数组的变化
vue在实现数组响应式时,它使用了一些hack,把无法监听数组的情况通过重写数组方法来实现响应式,这也只限于在数组的push、pop、shift、unshift、splice、sort、reserve这七个方法,其他数组方法及数组的使用则无法检测到。
例如:
vm.items[index] = newValue; //通过下标修改数组中的元素
vm.items.length
Vue实现数组响应式的方法:
通过重写数组Array.protytype中对应的方法,具体来讲就是要重新指定要操作的数组的prototype,并重写该prototype中对应的方法,通过一下代码简单了解一下实现原理:
const methods = ['pop','shift','unshift','sort','reverse','splice', 'push'];
// 复制Array.prototype,并将其prototype指向Array.prototype
let proto = Object.create(Array.prototype);
methods.forEach(method => {
proto[method] = function () { // 重写proto中的数组方法
Array.prototype[method].call(this, ...arguments);
viewRender() // 视图更新
function observe(obj) {
if (Array.isArray(obj)) { // 数组实现响应式
obj.__proto__ = proto; // 改变传入数组的prototype
return;
}
if (typeof obj === 'object') {
... // 对象的响应式实现
}
}
}
})
VUE3中实现数据双向绑定的方法
vue3.0实现数据双向绑定是通过 Proxy
Proxy 是ES6中新增的一个特性,翻译过来就是“代理”,在这里由它来表示代理某些操作。Proxy让我们能够以简洁易懂的当时控制外部对对象的访问,其功能类似于设计模式中的代理模式。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
使用 Proxy 的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。
语法:
let proxy = new Proxy(target, handler)
- target —— 是要包装的对象,可以是任何东西,包括函数。
- handler —— 代理配置:带有“捕捉器”(“traps”,即拦截操作的方法)的对象。比如 get 捕捉器用于读取 target 的属性,set 捕捉器用于写入 target 的属性,等等。
使用Proxy实现双向数据绑定的优势:
- 可以劫持整个对象,并返回一个新对象
- 有13种劫持操作
版权声明:本文为m0_63153901原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。