Skip to content

vue3实现数据双向绑定的数据挟持

约 497 字大约 2 分钟

vue3数据挟持Proxy

2025-05-22

vue3数据挟持原理

主要利用Proxy进行代理

Proxy介绍

const proxyData = new Proxy(target, proxyConf) 是 JavaScript 中创建代理对象的核心语法,用于拦截并自定义对目标对象 target 的操作

const proxy = new Proxy(target,proxyConf)
  • 核心参数

    1. target 目标对象

      可以是任何类型的对象(包括数组、函数、其他 Proxy 对象等)

      代理对象 proxyData 会继承 target 的原始行为,但通过 proxyConf 可以覆盖或增强这些行为。

    2. proxyConf 处理程序对象

      包含一系列 陷阱方法(Traps),用于拦截对 target 的操作

      若未定义某个陷阱方法,则默认执行原始操作(如直接访问 target 的属性)

代码实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button class="but">改变</button>
  <div class="content"></div>
  <script>
    // 利用Proxy

    const updateView = () => {
      console.log('视图跟新')
    }
    
    
    const reactive = (obj = {}) => {

      if (typeof obj !== "object" || obj == null) {
        return obj
      }
      // Proxy 处理程序对象
      const proxyConf = {
        get(target, key, receiver) {
          const keys = Reflect.ownKeys(target) // 获取属性
          if (keys.includes(key)) {
            console.log('获取数据成功')
          }
          // 获取值
          const value = Reflect.get(target, key, receiver)
          // 再次判断是否是对象
          return reactive(value)
        },

        set(target, key, newValue, receiver) {
          if (target[key] === newValue) return true
          const keys = Reflect.ownKeys(target)
          if (keys.includes(key)) {
            // 有属性 改变值 改变视图
            // target.key = newValue

          } else {
            // 增加属性
            target[key] = newValue
          }
          updateView()

          return Reflect.set(target, key, newValue, receiver)
        },
          // 删除操作
        deleteProperty(target, key) {
          delete target.key
          updateView()
        }
      }

      const proxy = new Proxy(obj, proxyConf)
      return proxy

    }

    const data = {
      name: 'haohao',
      age: 20,
      info: {
        city: 'shangtou',
        a: {
          b: {
            c: 100
          }
        }
      },
      test: "",
      nums: [1, 2, 3, 4]
    }

    const proxy = reactive(data)

    const content = document.querySelector('.content')
    const but = document.querySelector('.but')
    but.addEventListener('click', () => {

      // console.log(proxy.name)

      // console.log(proxy.info.a.b.c.d.e)
      // proxy.sex = 123
      // proxy.info.a.b.c.d.e = 23
      // console.log(proxy.info.a.b.c.d.e)
      // console.log(proxy)


    })

  </script>
</body>

</html>

优缺点

  • 深度监听性能更好
  • 可监听 新增 / 删除 属性
  • 可监听数组变化
  • Proxy 能规避 Object.defineProxy 的问题
  • Proxy 无法兼容所有浏览器,无法 polyfill