2018年11月16日,关注vue的人都知道这个时间点发生了什么事儿吧。vue3.0更新内容html
研究数据双向绑定的大佬们都在开始猜想这个新机制了,用原生Proxy替换Object.definePropertyvue
替换不是由于很差,是由于有更好的方法使用效率更高segmentfault
Object.defineProperty的缺点:设计模式
在Vue中,Object.defineProperty没法监控到数组下标的变化,致使直接经过数组的下标给数组设置值,不能实时响应。为了解决这个问题,通过vue内部处理后可使用如下几种方法来监听数组。有关于这个说明,能够看看这个文章 vue为何不能检测数组变更数组
push() pop() shift() unshift() splice() sort() reverse()
目前只针对以上方法作了hack处理,因此恰数组属性是检测不到的,有局限性。函数
Object.defineProperty只能劫持对象的属性,所以咱们须要对每一个对象的每一个属性进行遍历。Vue里,是经过递归以及遍历data对象来实现对数据的监控的,若是属性值也是对象那么须要深度遍历,显然若是能劫持一个完整的对象,无论是对操做性仍是性能都会有一个很大的提高。
而要取代它的Proxy有如下两个优势:性能
1. 能够劫持整个对象,并返回一个新对象 2. 有13种劫持操做
Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理",用在这里表示由它来“代理”某些操做。 Proxy 让咱们可以以简洁易懂的方式控制外部对对象的访问。其功能很是相似于设计模式中的代理模式。 Proxy 能够理解成,在目标对象以前架设一层“拦截”,外界对该对象的访问,都必须先经过这层拦截,所以提供了一种机制,能够对外界的访问进行过滤和改写。 使用 Proxy 的核心优势是能够交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,须要验证;某些属性的访问控制等)。 从而可让对象只需关注于核心逻辑,达到关注点分离,下降对象复杂度等目的。
基本用法:this
let p = new Proxy(target, handler);
参数:翻译
target: 是用Proxy包装的被代理对象(能够是任何类型的对象,包括原生数组,函数,甚至另外一个代理)。 handler: 是一个对象,其声明了代理target 的一些操做,其属性是当执行一个操做时定义代理的行为的函数。
p是Proxy对象,当其余操做对p进行更改的时候,会执行handler对象的方法。Proxy有13种数据劫持的操做,经常使用的handler处理方法:设计
get: 读取值, set: 获取值, has: 判断对象是否拥有该属性, construct: 构造函数
给个例子:
let obj = {}; let handler = { get(target, property) { console.log(`${property} 被读取`); return property in target ? target[property] : 3; }, set(target, property, value) { console.log(`${property} 被设置为 ${value}`); target[property] = value; } } let p = new Proxy(obj, handler); p.name = 'tom' //name 被设置为 tom p.age; //age 被读取 3
更多的Proxy属性方法参考MDN Proxy
observe(data) { const that = this; let handler = { get(target, property) { return target[property]; }, set(target, key, value) { let res = Reflect.set(target, key, value); that.subscribe[key].map(item => { item.update(); }); return res; } } this.$data = new Proxy(data, handler); }
这段代码里把代理器返回的对象代理到this.$data,即this.$data是代理后的对象,外部每次对this.$data进行操做时,实际上执行的是这段代码里handler对象上的方法。
注:这儿用到了reflect属性,这也是ES6里面的,不知道的去这儿看看吧。reflect属性
上面说到了怎么使用Proxy作数据劫持,怎么结合订阅发布,请结合 vue2.0数据双向绑定探究 对照着Object.defineProperty数据劫持的部分去替换看一下。其余的设计思想估计跟以前的八九不离十。