vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > Vue3 computed

深入理解Vue3 computed

作者:前端小巷子

本文主要介绍了Vue3 computed的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在模板里写一行 {{ sum }},背后却藏着「惰性求值 + 精准依赖收集 + 脏检查缓存」的三重魔法。本文带你钻进源码,拆解 computed 如何决定「何时算、何时不、为何不能异步」。

一、使用方法

const state = reactive({ a: 1, b: 2 })
const sum = computed(() => state.a + state.b)

console.log(sum.value) // 3
state.a = 10
console.log(sum.value) // 12

看似普通,但注意两点:

二、缓存机制:dirty 标志位

源码核心只有两行状态机:

let value: any
let dirty = true

首次读取 sum.value 时,dirty 从 true 变为 false,并把结果存入 value

当依赖的响应式数据变化,调度器把 dirty 重新置为 true,但不会立即计算,而是等待下一次读取。

这就是「缓存」的本质:用 1 bit 的布尔值换一次昂贵的计算。

三、依赖收集:effect 包裹 getter

computed 的计算函数被 effect 包装成副作用:

const effectFn = effect(getter, {
  lazy: true,
  scheduler() {
    dirty = true
    trigger(obj, TriggerOpTypes.SET, 'value')
  }
})

当模板读取 sum.valuetrack 把当前渲染副作用注册到 computed 的依赖图;当 state.a 变化,trigger 通知渲染器重新执行,渲染器再去读 sum.value,此时才真正触发计算。

四、为什么拒绝异步?

设想一个异步 computed:

const asyncSum = computed(async () => {
  const res = await fetch('/api/sum?a=' + state.a)
  return res.json()
})

问题立刻暴露:

  1. 缓存无法兑现

    第一次读取返回一个 Promise,第二次读取依赖并未变化,但缓存里存的是 Promise,无法直接返回结果。

  2. 渲染时数据缺位

    模板在渲染阶段需要同步值,异步导致视图出现空档或闪烁。

  3. 依赖追踪混乱

    异步完成时间不确定,期间若依赖再次变化,无法确定哪一次结果是最新。

Vue 官方给出的替代方案是 watch + ref

const asyncSum = ref(0)
watch(state, async () => {
  asyncSum.value = await fetch('/api/sum?a=' + state.a).then(r => r.json())
})

watch 不缓存、不阻塞渲染,天然适合异步副作用。

五、可写 computed:缓存 + setter 的双通道

const fullName = computed({
  get()   { return firstName.value + ' ' + lastName.value },
  set(v)  { [firstName.value, lastName.value] = v.split(' ') }
})

总结

computed 用「dirty 位 + 惰性 effect」实现同步缓存,用「拒绝异步」换取数据一致性。理解了这一点,你就掌握了 Vue 性能调优的第一把钥匙。

到此这篇关于深入理解Vue3 computed的文章就介绍到这了,更多相关Vue3 computed内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文