Vue3 之 ref 与 shallowRef,并手写实现 shallowRef 的拦截功能

5,688 阅读2分钟

ref

vue3 中一般用 ref 将一个值为基本数据类型的变量变成响应式的,它是一个函数,组合式 API 之一,参数为变量的初始值。举个栗子,比如我们需要一个响应式的变量 num,初始值为 1。在 vue2 中我们会这么做:

data() {
  return {
    num: 1
  }
}

num 写在 data 里。而在 vue3 中,我们通过在 setup 函数里使用 ref 定义 num,此时 num 成了一个类型为 Ref(reference) 的,包含响应式数据的引用对象 :

setup() {
  const num = ref(1)
}

现在,如果我们想在 js 中改变 num 的值,需要通过 num.value。在 ref 内部,是通过给 value 属性添加 getter/setter 来实现对数据的劫持的,这点在我们手写 shallowRef 时需要用上。

注意,在 <template> 内则不需要通过 .value 而是可以直接使用 num

shallowRef

只处理了 value 的响应式, 不进行对象的 reactive 处理,也就是说如果传给 shallowRef 一个对象,这个对象的任何一层属性都不是响应式的。

手写实现(拦截对数据的操作)

target 赋值给 _value 属性,通过对象本身的 setget 方法来实现对 target 的操作的拦截:

function shallowRef(target) {
  return {
    _value: target,
    get value() {
      console.log('拦截到查询')
      return this._value
    },
    set value(val) {
      console.log('拦截到修改')
      this._value = val
    }
  }
}

可以测试一下效果:

const testShallowRef = shallowRef('美好的')

打印查看 testShallowRef 对象本身 console.log(testShallowRef)

image.png

可以看到有个 value 属性,值为传递给 shallowRef 的参数。

testShallowRef 进行查改操作:

testShallowRef.value += '周五'

浏览器打印:

image.png
说明确实拦截到了对 testShallowRef 的查询和修改操作,那么就可以继续做一些更新渲染页面的功能。

本篇到此结束,vue3 的更多知识我也正在学习中,不足之处还望各位大佬不吝斧正~

感谢.gif

点赞.png