Skip to content

Latest commit

 

History

History
118 lines (91 loc) · 3.13 KB

isReactive和isReadonly.md

File metadata and controls

118 lines (91 loc) · 3.13 KB

isReactive

test('Object', () => {
  const original = { foo: 1 }
  const observed = reactive(original)

  expect(isReactive(observed)).toBe(true)
  expect(isReactive(original)).toBe(false)

})

可以检查对象是否是由 reactive创建的响应式代理。

找到isReactive定义的位置

/packages/reactivity/src/reactive.ts

export const enum ReactiveFlags {
  SKIP = '__v_skip',
  IS_REACTIVE = '__v_isReactive',
  IS_READONLY = '__v_isReadonly',
  RAW = '__v_raw'
}

export function isReactive(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE])
}

其实就是访问value的ReactiveFlags.IS_REACTIVE这个属性,然后就会触发代理对象中的get

function createGetter(isReadonly = false, shallow = false) {
  return function get(target: Target, key: string | symbol, receiver: object) {
    if (key === ReactiveFlags.IS_REACTIVE) {
      return !isReadonly
    } else if (key === ReactiveFlags.IS_READONLY) {
      return isReadonly
    } else if (
      key === ReactiveFlags.RAW &&
      receiver ===
        (isReadonly
          ? shallow
            ? shallowReadonlyMap
            : readonlyMap
          : shallow
          ? shallowReactiveMap
          : reactiveMap
        ).get(target)
    ) {
      return target
    }
  }
}

可以看到如果key是ReactiveFlags.IS_REACTIVE则返回!isReadonly

看下刚刚的例子,因为observed是调用reactive创建的对象,所以会在baseHandlers.ts文件中会走

const get = /*#__PURE__*/ createGetter()

因为isReadonly没有传参所以默认为false所以此时访问的ReactiveFlags.IS_REACTIVE返回的!isReadonly为true

而isReactive(original) 由于original[ReactiveFlags.IS_REACTIVE]是undefined ,所以返回false

isReadonly

it('should make nested values readonly', () => {
  const original = { foo: 1, bar: { baz: 2 } }
  const wrapped = readonly(original)
  expect(isReactive(wrapped)).toBe(false)
  expect(isReadonly(wrapped)).toBe(true)
  expect(isReactive(original)).toBe(false)
  expect(isReadonly(original)).toBe(false)
  expect(isReactive(wrapped.bar)).toBe(false)
  expect(isReadonly(wrapped.bar)).toBe(true)
  expect(isReactive(original.bar)).toBe(false)
  expect(isReadonly(original.bar)).toBe(false)
})

检查对象是否是由readonly创建的只读代理

isReadonly处理的方式和isReactive类似,isReadonly访问的是ReactiveFlags.IS_READONLY

export function isReadonly(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])
}

此时应该调用代理对象中的

const readonlyGet = /*#__PURE__*/ createGetter(true)

回忆一下createGetter,此时isReadonly是true,所以当key为ReactiveFlags.IS_READONLY直接返回isReadonly 则会true

嵌套的对象是当在访问的时候判断是否是对象递归处理

if (isObject(res)) {
  // Convert returned value into a proxy as well. we do the isObject check
  // here to avoid invalid value warning. Also need to lazy access readonly
  // and reactive here to avoid circular dependency.
  return isReadonly ? readonly(res) : reactive(res)
}