Skip to content

computed面试题

面试题:谈谈 computed 的机制,缓存了什么?为什么 computed 不支持异步?

响应式系统:

  • track:进行依赖收集,建立数据和函数的映射关系
  • trigger:触发更新,重新执行数据所映射的所有函数

computed开发者使用:

js
const state = reactive({
  a: 1,
  b: 2
})

const sum = computed(() => {
  return state.a + state.b
})
js
const firstName = ref('John')
const lastName = ref('Doe')

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

computed核心实现:

  1. 参数归一化,统一成对象的形式
  2. 返回一个存取器对象
js
import { effect } from "./effect/effect.js";
import track from "./effect/track.js";
import trigger from "./effect/trigger.js";
import { TriggerOpTypes, TrackOpTypes } from "./utils.js";

// 参数归一化
function normalizeParameter(getterOrOptions) {
  // 代码略
}

/**
 *
 * @param {*} getterOrOptions 可能是函数,也可能是对象
 */
export function computed(getterOrOptions) {
  // 1. 参数归一化
  const {getter, setter} = normalizeParameter(getterOrOptions);
  
  // value 用于存储计算结果, dirty 负责控制从缓存中获取值还是重新计算新的值,dirty为true就代表要重新计算
  let value, dirty = true;
  
  // 让getter内部的响应式数据和getter建立映射关系
  // 回头getter内部的响应式数据发生变化后,重新执行getter
  const effectFn = effect(getter, {
    lazy: true,
    scheduler(){
      dirty = true;
      trigger(obj, TriggerOpTypes.SET, "value")
    }
  })
  
  
  // 2. 返回一个存取器对象
  const obj = {
    get value(){
      // 需要将 value 和渲染函数建立映射关系
      track(obj, TrackOpTypes.GET, "value")
      if(dirty){
        value = effectFn()
        dirty = false;
      }
      return value;
    },
    set value(newValue){
      setter(newValue)
    }
  }
  return obj;
}

面试题:谈谈 computed 的机制,缓存了什么?为什么 computed 不支持异步?

参考答案:

谈谈 computed 的机制,缓存了什么?

缓存的是上一次 getter 计算出来的值。

为什么 computed 不支持异步?

computed 属性在 Vue 中不支持异步操作的主要原因是设计上的理念和使用场景的考虑。computed 属性的初衷是用于计算并缓存一个基于响应式依赖的同步计算结果,当其依赖的响应式数据发生变化时,Vue 会自动重新计算 computed 的值,并将其缓存,以提高性能。

computed 不支持异步的几个具体原因:

  1. 缓存机制与同步计算:computed 属性的一个核心特性是缓存。当依赖的响应式数据没有变化时,computed 的计算结果会被缓存并直接返回,而不会重新执行计算。这种缓存机制是基于同步计算的,假如允许异步计算,那么在异步操作完成之前,computed 属性无法提供有效的返回值,这与它的同步缓存理念相违背。
  2. 数据一致性:computed 属性通常用于模板中的绑定,它的计算结果需要在渲染期间是稳定且可用的。如果 computed 支持异步操作,渲染过程中的数据可能不一致,会导致模板渲染时无法确定使用什么数据,从而可能造成视图的闪烁或数据错误。
  3. 调试与依赖追踪困难:如果 computed 属性是异步的,那么在调试和依赖追踪时就会变得非常复杂。异步操作的完成时间不确定,会使得依赖追踪的过程变得不直观,也难以预期。

如果需要进行异步操作,通常推荐使用 watch 来实现。


-EOF-

Released under the MIT License.