美文网首页
Vue3.0 toRaw函数和markRaw函数

Vue3.0 toRaw函数和markRaw函数

作者: 抽疯的稻草绳 | 来源:发表于2021-03-22 14:28 被阅读0次

    Vue3.0给我们提供的这两个方法,toRaw方法是把被reactive或readonly后的Proxy对象转换为原来的target对象,而markRaw则直接让target不能被reactive或readonly。

    先看看toRaw怎么用,

           setup(){       
              let obj = {
                msg: 'hello',
                student: {
                  name: 'xiaoliu',
                  age: 20
                }
              }
              let reactiveObj = reactive(obj)
              let state = toRaw(reactiveObj)    
              return {state}
            }
    

    用法很简单,看看转换前后Proxy对象和target对象:

    image.png

    上图是进行reactive后的Proxy对象,看看对其toRaw后,


    image.png

    toRaw后,Proxy对象又被转换回去了。还记得在调用createReactiveObject进行Proxy时,用WeakMap数据结构把target和Proxy对象联系起来了:proxyMap.set(target, proxy)。

    toRaw就通过Proxy把target给提取出来,看看具体怎么做的:

    export function toRaw<T>(observed: T): T {
      return (
        (observed && toRaw((observed as Target)[ReactiveFlags.RAW])) || observed
      )
    }
     
     
    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 ? readonlyMap : reactiveMap).get(target)
        ) {
          //在这里把通过比较Proxy,把target给找出来
          return target
        }
    

    如果传给toRaw的参数不是Proxy对象则原样返回。

    接下来看看markRaw方法,

    export function markRaw<T extends object>(value: T): T {
      //给target增加一个ReactiveFlags.SKIP属性
      def(value, ReactiveFlags.SKIP, true)
      return value
    }
     
    export const def = (obj: object, key: string | symbol, value: any) => {
      Object.defineProperty(obj, key, {
        configurable: true,
        enumerable: false,
        value
      })
    }
     
    function getTargetType(value: Target) {
      //判断如果target有ReactiveFlags.SKIP属性,则直接判断不在可以进行reactive的白名单中,从而不能进行reactive
      return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)
        ? TargetType.INVALID
        : targetTypeMap(toRawType(value))
    }
    

    markRaw通过增加一个属性标志ReactiveFlags.SKIP,来判断是否能进行reactive,非常简单,不再进行表述了。

    toRaw在实际的业务开发中感觉用的频次应该比较低。

    相关文章

      网友评论

          本文标题:Vue3.0 toRaw函数和markRaw函数

          本文链接:https://www.haomeiwen.com/subject/dmmzcltx.html