实现 toRaw

在本小节中,我们将会实现 toRaw API

1. happy path

先看测试样例

it('happy path', () => {
    // toRaw 可以 return 通过 `reactive` 、 `readonly` 、`shallowReactive` 、`shallowReadonly` 包装的 origin 值
    const reactiveOrigin = { key: 'reactive' }
    expect(toRaw(reactive(reactiveOrigin))).toEqual(reactiveOrigin)
    const readonlyOrigin = { key: 'readonly' }
    expect(toRaw(readonly(readonlyOrigin))).toEqual(readonlyOrigin)
    const shallowReadonlyOrigin = { key: 'shallowReadonly' }
    expect(toRaw(shallowReadonly(shallowReadonlyOrigin))).toEqual(
        shallowReadonlyOrigin
    )
    const shallowReactiveOrigin = { key: 'shallowReactive' }
    expect(toRaw(shallowReactive(shallowReactiveOrigin))).toEqual(
        shallowReactiveOrigin
    )

    const nestedWrapped = {
        foo: { bar: { baz: 1 }, foo2: { bar: { baz: 2 } } },
    }
    expect(toRaw(reactive(nestedWrapped))).toEqual(nestedWrapped)
})

通过测试样例我们发现,toRaw 的作用就是将包装过的值的原始值返回回来,同时我们嵌套的值也要嵌套转换回来

// reactive.ts

// 创建 RAW 枚举
export const enum ReactiveFlags {
  IS_REACTIVE = '__v_isReactive',
  IS_READONLY = '__v_isReadonly',
  RAW = '__v_raw',
}


export function toRaw(observed) {
  // 这里就是嵌套转换了
  const original = observed && observed[ReactiveFlags.RAW]
  return isProxy(original) ? toRaw(original) : original
}
// baseHandlers


function createGetter(isReadonly = false, shallow = false) {
  return function get(target, key, receiver) {
    if (key === ReactiveFlags.IS_REACTIVE) {
      return !isReadonly
    } else if (key === ReactiveFlags.IS_READONLY) {
      return isReadonly
    } else if (key === ReactiveFlags.RAW) {
      // 判断一下,如果访问的 key 是 ReactiveFlag.RAW,就直接返回就可以了
      return target
    }
    // other code ...
  }
}