使用:

    1. const myAge = computed({
    2. get(){},
    3. set(){},
    4. })
    5. const myAge = computed(() =>{
    6. return age.value + 10;
    7. })
    8. effect(()=>{
    9. console.log(myAge.value);
    10. })

    特性:

    • 此方法默认不会执行
    • 当访问属性的时候执行
    • 当依赖属性变了不会立即重新计算,而是等下次再去访问的时候才会重新计算
    1. class ComputedRefImpl<T> {
    2. private _value!: T // 操作 的 value
    3. private _dirty = true // 脏
    4. public readonly effect: ReactiveEffect<T>
    5. public readonly __v_isRef = true;
    6. public readonly [ReactiveFlags.IS_READONLY]: boolean
    7. constructor(
    8. getter: ComputedGetter<T>, // 就是我们在 computed 里面写的函数
    9. private readonly _setter: ComputedSetter<T>,
    10. isReadonly: boolean
    11. ) {
    12. // 计算属性默认会生成一个effect
    13. this.effect = effect(getter, {
    14. lazy: true, // 默认初始化不执行,当取值的时候才会执行
    15. scheduler: () => { // 这个 scheduler 的作用是当我设置了 computed 里面的某个值后希望他能重新执行,就需要把_dirty 设置为true
    16. if (!this._dirty) {
    17. this._dirty = true
    18. // 属性变化了更新
    19. trigger(toRaw(this), TriggerOpTypes.SET, 'value')
    20. }
    21. }
    22. })
    23. this[ReactiveFlags.IS_READONLY] = isReadonly
    24. }
    25. get value() { // 计算属性也要收集依赖
    26. // the computed ref may get wrapped by other proxies e.g. readonly() #3376
    27. const self = toRaw(this)
    28. if (self._dirty) {
    29. self._value = this.effect() // effect 会执行 fn 并返回结果
    30. self._dirty = false // 缓存
    31. }
    32. /**
    33. * 如果在 effect 中使用了 计算属性 计算后的值的话就需要 依赖收集
    34. * effect(()=>{
    35. * console.log(myAge.value);
    36. * })
    37. * 当访问了 value 属性时就会收集
    38. */
    39. track(self, TrackOpTypes.GET, 'value')
    40. return self._value
    41. }
    42. set value(newValue: T) {
    43. this._setter(newValue)
    44. }
    45. }
    46. export function computed<T>(getter: ComputedGetter<T>): ComputedRef<T>
    47. export function computed<T>(
    48. options: WritableComputedOptions<T>
    49. ): WritableComputedRef<T>
    50. /**
    51. * 以下两种情况:
    52. * const myAge = computed({
    53. get(){},
    54. set(){},
    55. })
    56. const myAge = computed(() =>{
    57. return age.value + 10;
    58. })
    59. * 此方法默认不会执行
    60. * 当访问属性的时候执行
    61. * 当依赖属性变了不会立即重新计算,而是等下次再去访问的时候才会重新计算
    62. *
    63. * vue2 和 vue3 computer 原理是不一样的
    64. * vue2 是让 computed 依赖的属性记住 那个渲染 watcher
    65. */
    66. export function computed<T>(
    67. getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
    68. ) {
    69. let getter: ComputedGetter<T>
    70. let setter: ComputedSetter<T>
    71. // 判断是不是一个 函数
    72. if (isFunction(getterOrOptions)) {
    73. getter = getterOrOptions
    74. setter = __DEV__
    75. ? () => {
    76. console.warn('Write operation failed: computed value is readonly')
    77. }
    78. : NOOP
    79. } else {
    80. getter = getterOrOptions.get
    81. setter = getterOrOptions.set
    82. }
    83. return new ComputedRefImpl(
    84. getter,
    85. setter,
    86. isFunction(getterOrOptions) || !getterOrOptions.set
    87. ) as any
    88. }