前言:大家都是到Vue2.0 的双向绑定是通过 Object.defineProperty 来劫持对象的setter 和 getter 方法来实现的。但是呢,,,,
对于对象
- Object.defineProperty 无法检测到 对象的添加或者移除,由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应式的
vm.b = 2
// `vm.b` 是非响应式的
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
this.$set(this.someObject,'b',2)
- 对于如下 people 对象,如果用 Object.defineProperty 就得遍历people逐个绑定,需要绑定4次,这样很不方便,而用proxy 可以劫持整个对象。
const people = {
name: 'Jim',
sex:'男',
height:'180',
married:'yes'
}
const handler = {
get: (obj, prop) => {
console.log(obj[prop])
},
set : (obj, prop) => {
console.log(obj[prop])
}
}
const target = new Proxy(people, handler);
对于数组
Object.defineProperty 无法监控到数组下标的变化,比如:
- 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:vm.items.length = newLength
为了解决这个问题 Vue2.0 内部通过重写数组的8个方法来监听数组。但是指针对着8 个方法有一定的局限性。
所以Vue 3.0 使用了Proxy。。。。。。
具体使用参考官方文档 或者 https://www.jianshu.com/p/bd53624f1a86
</br>
对比
Proxy 优势如下
- Proxy 可以直接监听对象而非属性;
- Proxy 可以直接监听数组的变化;
- Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是Object.defineProperty 不具备的;
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
- Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
Object.defineProperty 的优势如下:
兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。