【mini vue】实现readonly

104 阅读1分钟

主要思路

封装createGetter 和 createSetter函数,这两个函数分别返回get 和 set方法,同时将一个布尔值作为参数传入,判断当前对象是否是readOnly的,根据这个参数对get 和 set方法做不同的处理。

一些细节点

封装createGetter 和 createSetter函数:

抽离函数:相同逻辑的代码可以将其抽离成一个函数,参数不一样就行,增加代码的可读性。

function createGetter(isReadOnly = false) {
  return function get(target, key) {
    const res = Reflect.get(target, key)
    if (!isReadOnly) {
      // 收集依赖
      track(target, key)
    }
    return res
  }
}

function createSetter() {
  return function set(target, key, value) {
    const res = Reflect.set(target, key, value)
    // 触发依赖
    trigger(target, key)
    return res
  }
}

抽离baseHandle, 逻辑代码相同的抽离成一个函数,增加代码的可读性

import { mutableHandlers, readonlyHandlers } from "./baseHandlers"

export function reactive(raw) {
  return createActiveObject(raw, mutableHandlers)
}

export function readonly(raw) {
  return createActiveObject(raw, readonlyHandlers)
}

function createActiveObject(raw: any, baseHandlers: any) {
  return new Proxy(raw, baseHandlers)
}

缓存:避免每次读或写数据的时候都要重新创建getter 和 setter函数,只让 get 或 set 函数在初始化的时候创建一次,后续需要使用get 或者 set 方法的时候复用这个函数就行。

(优化之前的代码)

const get = createGetter()
const set = createGetter()
const readonlyGet = createGetter(true)

export const mutableHandlers = {
  get,
  set,
}

export const readonlyHandlers =  {
  get: readonlyGet,
  set(target, key, value) {
    return true
  },
}

(优化之后的代码)

const get = createGetter()
const set = createGetter()
const readonlyGet = createGetter(true)

export const mutableHandlers = {
  get,
  set,
}

export const readonlyHandlers =  {
  get: readonlyGet,
  set(target, key, value) {
    return true
  },
}