Skip to content

Proxy代理

专题简介

在ES6之前,我们常使用Object.defineProperty()方法来进行数据代理从而实现数据的劫持(如:Vue2的响应式原理)

而在ES6之后诞生了一个全新的对象(构造器):Proxy,作为数据代理而言,它比Object.defineProperty()要强大许多,这也是为什么Vue3的响应式要使用Proxy来做的原因

为什么要使用代理

之所以使用代理,就是不希望用户能够直接访问某个对象,直接操作对象的某个成员(因为这样是不可控的,我们不知道用户在访问操作哪一个对象)

通过代理,我们可以拦截用户的访问(称为数据劫持),拦截住后我们就可以对数据进行一些处理,比如做一些数据的验证或者像Vue一样做一些视图更新的额外操作,之后再允许用户的访问操作(因为我们拦截了用户的每一次访问,这样用户操作对象就完全是在我们可控的范围内)

简单来说,就是我们希望用户在访问对象时我们能够清楚的知道用户在访问什么并且能够在中间做一些我们自己的操作

Proxy是什么?

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)

注释

Proxy 是 ES6 中新增的一个构造函数,也可以叫类,通过new操作符调用使用。 但在JavaScript中函数和类本质上也是对象,所以我们也能将Proxy 直接作为对象访问它的属性进行操作,如Proxy.revocable()

基础语法

js
const proxyTarget = new Proxy(target, handler)

参数

  • target:Proxy 会对 target 对象进行包装。它可以是任何类型的对象,包括内置的数组,函数甚至是另一个代理对象。
  • handler:它是一个对象,它的属性提供了某些操作发生时所对应的处理函数。

注释

一个空的 handler 参数将会创建一个与被代理对象行为几乎完全相同的代理对象。通过在 handler 对象上定义一组处理函数,你可以自定义被代理对象的一些特定行为。例如, 通过定义 get() 你就可以自定义被代理对象的 属性访问器。

返回值

  • proxyTarget :经过Proxy包装后的target对象

基础使用实例

js
const obj = {
    name: 'Ailjx'
}
const proxyTarget = new Proxy(obj, {
    set:function(){

    }
})
console.log(proxyTarget);

vue3中的prxoy和es6的proxy有何不同?

在Vue3中,Proxy是Vue3内部使用的一个对象,它和ES6中的Proxy是有所不同的。 Vue3中,Proxy被用来实现响应式数据的追踪和更新。当我们使用reactive或ref函数创建响应式数据时,Vue3内部会使用Proxy对这些数据进行代理,并在数据发生变化时自动触发相关的更新操作。

这种代理机制可以帮助我们更好地追踪数据的变化,并且可以避免一些不必要的更新操作,从而提高程序的性能。

以reactive函数为例,它的实现原理如下

js
function reactive(target) {
  // 使用Proxy对目标对象进行代理
  const proxy = new Proxy(target, {
    get(target, key) {
      // 在获取属性时收集依赖
      track(target, key)
      return Reflect.get(target, key)
    },
    set(target, key, value) {
      const oldValue = target[key]
      if (oldValue !== value) {
        // 在设置属性时触发更新
        Reflect.set(target, key, value)
        trigger(target, key)
      }
      return true
    }
  })
  return proxy
}

不同

  • 用途不同: ES6中的Proxy主要用来代理普通的JavaScript对象,可以在访问或修改对象属性时拦截并执行一些自定义的逻辑。而Vue3中的Proxy主要用来实现响应式数据的追踪和更新,可以在数据发生变化时自动触发相关的更新操作。

  • 实现方式不同: ES6中的Proxy是一个原生的JavaScript对象,需要使用ES6的语法来创建和使用。而Vue3中的Proxy是Vue3内部实现的一个对象,我们无法直接访问和使用它。

  • 用法不同: ES6中的Proxy需要手动创建和使用,需要定义一个handler对象来实现拦截器。而Vue3中的Proxy是自动创建和使用的,我们只需要使用reactive或ref函数来创建响应式数据,就可以自动获得Proxy的功能。

proxy对js和vue3来说有什么含义?

  • 对于JavaScript来说,Proxy是一个非常强大的特性,它可以帮助我们更好地控制对象的行为,从而实现一些高级的功能,例如数据绑定、状态管理、事件触发等等。

  • 在Vue3中,Proxy被用来实现响应式数据的追踪和更新,这使得我们可以更好地追踪数据的变化,并且可以避免一些不必要的更新操作,从而提高程序的性能。

  • 对于JavaScript和Vue3来说,Proxy的作用如下: 实现数据响应式:在Vue3中,使用Proxy代理响应式数据,可以自动追踪数据的变化并且自动触发相关的更新操作,从而实现数据的响应式。

  • 实现数据绑定:在JavaScript中,使用Proxy可以拦截对象的访问和修改,从而实现数据的绑定,当数据发生变化时,相关的组件会自动更新。

  • 实现状态管理:在Vue3中,使用Proxy可以实现一些高级的状态管理功能,例如状态共享、状态合并、状态持久化等等。

  • 实现事件触发:在JavaScript中,使用Proxy可以拦截对象的方法调用,从而实现事件的触发和监听,当事件发生时,相关的回调函数会自动执行。

  • 总之,对于JavaScript和Vue3来说,Proxy是一个非常重要的特性,它可以帮助我们更好地控制对象的行为,从而实现一些高级的功能。

proxy的封装机制

在Vue3中,Proxy是一个偏底层的东西,它被用来实现响应式数据的追踪和更新,是Vue3响应式系统的核心之一。Vue3内部使用Proxy对响应式数据进行代理,从而可以自动追踪数据的变化,并且可以自动触发相关的更新操作。在代理过程中,Vue3内部封装了一些机制,例如依赖追踪、更新队列等等,这些机制可以帮助我们更好地控制数据的变化和更新。

具体来说,Vue3内部封装的机制如下:

  • 依赖追踪:在获取响应式数据的属性时,Vue3会自动收集相关的依赖关系,从而可以在数据发生变化时自动触发相关的更新操作。

  • 延迟更新:在数据发生变化时,Vue3会将相关的更新操作添加到更新队列中,然后等待下一个事件循环周期再执行更新操作,从而避免一些不必要的更新操作。

  • 批量更新:在更新队列中可能存在多个更新操作,为了提高性能,Vue3会将它们合并成一个更新操作,然后一次性执行。 嵌套更新:在更新操作中可能会触发另一个更新操作,为了避免死循环,Vue3会限制最大的更新深度,并且在超过深度限制时抛出错误。

  • 总之,Vue3内部封装了一些机制来支持响应式数据的追踪和更新,这些机制可以帮助我们更好地控制数据的变化和更新,并且可以提高程序的性能。