手写mini版本的Vue3--实现 isRef 和 unRef 功能 & 实现 proxyRefs 功能

516 阅读2分钟

介绍

开头继续感谢崔大的mini-vue 项目。

项目地址:github.com/cuixiaorui/…

强烈建议大家把项目 down 下来,运行一下,看VUE3 的整体运行逻辑。

实现 isRef 和 unRef 功能

isRef 这个是用来判断一个值是否是一个 ref。

实现也很简单,在RefImpl 这个创建 ref 的类里面加上一个属性__v_isRef,这个属性为 true 就可以。

可以直接返回判断值的__v_isRef这个属性。

然后我们再处理一下如果传入的是一个普通的值,也就是没有__v_isRef这个值,返回是一个 undefined,我们再用!!转成布尔值就可以了。

class RefImpl { 
    public __v_isRef = true;    
 }
 
export function isRef(ref) {
  return !!ref.__v_isRef;
}

unRef 这个方法也很简单,判断一下传入值是否是一个 ref,如果是 ref 就返回 传入值.value,如果不是,返回传入值。

export function unRef(ref) {
 return isRef(ref) ? ref.value : ref;
}


实现 proxyRefs 功能

这个方法我们在写模板,也就是 HTML 里面使用 ref 不需要手动加上 .vulue 的原因,自动帮我们使用了这个方法。

export function proxyRefs(objectWithRefs) {
  return new Proxy(objectWithRefs, {
    get(target, key) {
      return unRef(Reflect.get(target, key))
    },
    set(target, key, value) {
      if (isRef(target[key]) && !isRef(value)) {
        return (target[key].value = value)
      } else {
        return Reflect.set(target, key, value)
      }
    }
  })
}

要实现这样子一个方法,其实就是用到了Proxy 的 get,set

这个 get 的逻辑其实就是 unRef ,判断一下传入值是否是一个 ref,如果是 ref 就返回 传入值.value,如果不是,返回传入值。

set 的逻辑,如果是一个 key 是一个 ref,并且值不是一个 ref 的时候,我们就设置 target的.value 等于新传入的值。

不然就直接 Reflect set 设置新的值就可以了

结尾

项目已经放到我的 GitHub 上面了,欢迎大家去start。

本次 commit地址:

github.com/moyuhaokan/…

github.com/moyuhaokan/…

我的项目地址:github.com/moyuhaokan/…

再次推荐崔大的项目:github.com/cuixiaorui/…