深入响应式原理

发布于 2025-03-05 06:21:03 字数 2147 浏览 6 评论 0

// 维持一个执行副作用的栈
const runningEffects = [] // 当前正在运行的副作用

const createEffect = fn => {
  // 将传来的 fn 包裹在一个副作用函数中
  const effect = () => {
    runningEffects.push(effect)
    fn()
    runningEffects.pop()
  }

  // 立即自动执行副作用
  effect()
}

createEffect(() => {
  sum = val1 + val2
})

Proxy 是一个对象,它包装了另一个对象,并允许你拦截对该对象的任何交互。

我们这样使用它:new Proxy(target, handler)

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, property) {
    console.log('intercepted!')
    return target[property]
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// intercepted!
// tacos

使用 Proxy 的一个难点是 this 绑定。我们希望任何方法都绑定到这个 Proxy,而不是目标对象,这样我们也可以拦截它们。值得庆幸的是,ES6 引入了另一个名为 Reflect 的新特性,它允许我们以最小的代价消除了这个问题:

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, property, receiver) {
    return Reflect.get(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// tacos

使用 Proxy 实现响应性的第一步就是跟踪一个 property 何时被读取。我们在一个名为 track 的处理器函数中执行此操作,该函数可以传入 target 和 property 两个参数。

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, property, receiver) {
    track(target, property)
    return Reflect.get(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// tacos

这里没有展示 track 的实现。它将检查当前运行的是哪个副作用,并将其与 target 和 property 记录在一起。这就是 Vue 如何知道这个 property 是该副作用的依赖项。

最后,我们需要在 property 值更改时重新运行这个副作用。为此,我们需要在代理上使用一个 set 处理函数:

const dinner = {
  meal: 'tacos'
}

const handler = {
  get(target, property, receiver) {
    track(target, property)
    return Reflect.get(...arguments)
  },
  set(target, property, value, receiver) {
    trigger(target, property)
    return Reflect.set(...arguments)
  }
}

const proxy = new Proxy(dinner, handler)
console.log(proxy.meal)

// tacos

现在,我们对 Vue 如何实现这些关键步骤有了答案:

1、当一个值被读取时进行追踪:proxy 的 get 处理函数中 track 函数记录了该 property 和当前副作用。
2、当某个值改变时进行检测:在 proxy 上调用 set 处理函数。
3、重新运行代码来读取原始值:trigger 函数查找哪些副作用依赖于该 property 并执行它们。

该被代理的对象对于用户来说是不可见的,但是在内部,它们使 Vue 能够在 property 的值被访问或修改的情况下进行依赖跟踪和变更通知。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

讽刺将军

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文