12、带你一步步实现vue3源码之shallowReadonly

235 阅读1分钟

shallowReadonly

这一节,我们一起来实现shallowReadonly,从字面意思就是表层只读。

编写测试

从单测可以看出,通过shallowReadonly创建的是表层只读的响应式对象。

// src/reactivity/tests/shallowReadonly.spec.ts
import {isReadonly, shallowReadonly} from '../reactive'
describe("shallowReadonly", () => {
  test("should not make non-reactive properties reactive", () => {
    const props = shallowReadonly({n: {foo: 1}})
    expect(isReadonly(props)).toBe(true)
    expect(isReadonly(props.n)).toBe(false)
  })
})

编码

reactive.ts中添加一个shallowReadonly函数,同样接收一个对象。

// src/reactivity/reactive.ts
import { mutableHandlers, readonlyHandlers, shallowReadonlyHandlers } from './baseHandlers'
...
export function shallowReadonly (raw) {
  return new Proxy(raw, shallowReadonlyHandlers)
}

同样,我们需要在createGetter中处理响应式对象的返回值,添加一个shallow参数,判断当前是否是shallow类型的,如果是,直接返回res即可

const shallowReadonlyGet = createGetter(true, true)

function createGetter (isReadonly = false, shallow = false) {
  return function get (target, key) {
    ...
    if (shallow) {
      return res
    }
    ...
  }
}

最后,还需要返回shallowReadonlyHandlers,是一个包含getset的对象,由于他也属于readonly,所以他也不能被赋值,所以下面我们这么写

export const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
  get: shallowReadonlyGet
})

让他继承readonlyHandlers,并且对他的get重新赋值。

总结

创建一个新的函数shallowReadonly来返回一个表层只读的响应式对象,通过改写createGetter的逻辑,添加shallow参数来分别类型,并处理他的返回值。