computed

传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。

  1. const count = ref(1)
  2. const plusOne = computed(() => count.value + 1)
  3. console.log(plusOne.value) // 2
  4. plusOne.value++ // 错误!

或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。 ```js const count = ref(1) const plusOne = computed({ get: () => count.value + 1, set: (val) => { count.value = val - 1 }, })

plusOne.value = 1 console.log(count.value) // 0

  1. 更多文档: [https://vue3js.cn/vue-composition-api/#computed](https://vue3js.cn/vue-composition-api/#computed)
  2. ### 正文
  3. 计算属性,可能会依赖其他 `reactive` 的值,同时会延迟和缓存计算值
  4. ```js
  5. export function computed<T>(
  6. getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
  7. ) {
  8. let getter: ComputedGetter<T>
  9. let setter: ComputedSetter<T>
  10. // 如果传入是 function 说明是只读 computed
  11. if (isFunction(getterOrOptions)) {
  12. getter = getterOrOptions
  13. setter = __DEV__
  14. ? () => {
  15. console.warn('Write operation failed: computed value is readonly')
  16. }
  17. : NOOP
  18. } else {
  19. // 不是方法说明是自定义的 getter setter
  20. getter = getterOrOptions.get
  21. setter = getterOrOptions.set
  22. }
  23. let dirty = true
  24. let value: T
  25. let computed: ComputedRef<T>
  26. // 创建 effect, 我们在看 effect 源码时知道了传入 lazy 代表不会立即执行,computed 表明 computed 上游依赖改变的时候,会优先 trigger runner effect, scheduler 表示 effect trigger 的时候会调用 scheduler 而不是直接调用 effect
  27. const runner = effect(getter, {
  28. lazy: true,
  29. // mark effect as computed so that it gets priority during trigger
  30. computed: true,
  31. scheduler: () => {
  32. // 在触发更新时把dirty置为true, 不会立即更新
  33. if (!dirty) {
  34. dirty = true
  35. trigger(computed, TriggerOpTypes.SET, 'value')
  36. }
  37. }
  38. })
  39. // 构造一个 computed 返回
  40. computed = {
  41. __v_isRef: true,
  42. // expose effect so computed can be stopped
  43. effect: runner,
  44. get value() {
  45. // dirty为ture, get操作时,执行effect获取最新值
  46. //
  47. if (dirty) {
  48. value = runner()
  49. dirty = false
  50. }
  51. // dirty为false, 表示值未更新,直接返回
  52. track(computed, TrackOpTypes.GET, 'value')
  53. return value
  54. },
  55. set value(newValue: T) {
  56. setter(newValue)
  57. }
  58. } as any
  59. return computed
  60. }