vue3为什么选择了proxy,proxy有哪些好玩的特性
vue3发布以来,不少大佬在网上都对 vue2 和 vue3进行了全方位的对比,其中有一个很重要的改动是弃用 Object.defineProperty,使用了性能更好、开发更加简便的 Proxy。 Proxy 翻译成中文就是“代理”,从其名称我们就能大致了解其功能。下面让我们从几个角度重新了解一下proxy吧: Proxy 是什么Object.defineProperty 是什么,与 Proxy 的区别Proxy 有哪些好玩的场景 Proxy 是什么 Proxy 用于创建对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。 const p = new Proxy(target, handler)
target:要使用 Proxy 包装的目标对象。 handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。 handler 对象常用方法(点我查看 Proxy 文档): handler.get() 属性读取操作的捕捉器。handler.set() 属性设置操作的捕捉器。handler.apply() 函数调用操作的捕捉器。handler.construct() new 操作符的捕捉器。/* 数字格式化 */
const target = {}
const handler = {
get: function(target, prop){
let str
const value = target[prop]
if( typeof(value) != 'number' ){
str = '--'
}else if( value < 1000 ){
str = value
}else if( value < 10000000 ){
str = `${parseInt(value/1000)}K`
}else{
str = `${parseInt(value/10000000)}KW`
}
return str
}
}
const p = new Proxy(target, handler)
p.a = 10000
console.log(p.a, target.a) //10K 10000
Object.defineProperty 是什么,与 Proxy 的区别 要了解 Proxy 与 Object.defineProperty 的区别,首先我们先回顾一下 Object.defineProperty 的用法。 Object.defineProperty() 用于对象属性的操作(新增或修改),并返回此对象。 Object.defineProperty(obj, prop, descriptor)
obj:要定义属性的对象。 prop:要定义或修改的属性的名称或 Symbol 。 descriptor:要定义或修改的属性描述符。 descriptor 配置对象的常用属性(点我查看 Object.defineProperty 文档): configurable 为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。value 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。writable 为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变。get 属性的 getter 函数,如果没有 getter,则为 undefined。set 属性的 setter 函数,如果没有 setter,则为 undefined。var o = {}
var bValue = 38
Object.defineProperty(o, "a", {
get() { return bValue; },
set(newValue) { bValue = newValue; },
configurable : true
})
o.a // 38
上面列举了 Proxy 和 Object.defineProperty 的使用方法和特性,通过对比可以看出这两种的区别主要体现在: Proxy 代理整个对象,Object.defineProperty 只代理对象上的某个属性。如果需要递归对象内的属性,Proxy 可以在调用时实现递归,Object.defineProperty 则需要在每个属性内重复执行相关操作,前者更加方便;Proxy 对代理对象的监听更加丰富。有且不限于以下场景:Proxy 可以监听对象新属性的定义(construct)和函数操作的调用(apply),而 Object.defineProperty 无法实现;Prxoy 代理对象会生成一个新的对象,不会修改被代理对象本身;Object.defineProperty 则是直接修改被代理对象的属性。proxy 不兼容IE浏览器,而 Object.defineProperty 则兼容IE8+。在IE浏览器环境下实现Proxy,需要额外引入 Proxy 兼容库。[图片] Proxy 有哪些好玩的场景 通过对 Proxy 的了解,我们可以得知其有两个重要特性:数据监控、功能扩展。围绕这些特性我们可以将 Proxy 用于以下场景: 日志记录 对于用户行为、接口请求、异常抛出、可能出现内存占用过大的场景,我们希望对其进行记录,这个时候就可以使用 Proxy 充当中间件的角色,轻而易举实现日志功能。 校验模块抽离 如果要直接为对象的所有属性开发一个校验器,可能会让代码结构变得臃肿,使用 Proxy 则可以将校验器从核心逻辑分离出来自成一体。 文案格式化 计算数据和展示文案不一致,数据又可能同时在多处修改的时候;如果没有 Proxy,我们需要同时为数据定义两个变量进行存储,每次数据修改时都需要同时对变量进行修改,很容易出现逻辑遗漏;使用 Proxy 的话,我们就可以通过监听计算数据的变化,实时更新展示文案。 避免对象属性覆盖 我们对对象属性的新增往往没有任何监控手段,容易造成原有属性的覆盖;这种场景我们使用 Proxy 监控对象的 set 操作,如果发现新增的属性已存在就进行异常抛出,如果是对属性的赋值,我们直接对源对象进行操作即可。