vue3为什么选择了proxy,proxy有哪些好玩的特性
发布于 3 年前 作者 suxiulan 1141 次浏览 来自 分享

vue3发布以来,不少大佬在网上都对 vue2 和 vue3进行了全方位的对比,其中有一个很重要的改动是弃用 Object.defineProperty,使用了__性能更好__、__开发更加简便__的 Proxy。

Proxy 翻译成中文就是“代理”,从其名称我们就能大致了解其功能。下面让我们从几个角度重新了解一下proxy吧:

  1. Proxy 是什么
  2. Object.defineProperty 是什么,与 Proxy 的区别
  3. 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]
    iftypeof(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 操作,如果发现新增的属性已存在就进行异常抛出,如果是对属性的赋值,我们直接对源对象进行操作即可。

回到顶部