跳至主要內容

ref 相关

wzCoding大约 3 分钟VueVue3ref 相关

ref 相关

ref 函数是 Vue3 中用于创建响应式数据的方法之一,也是 Vue3 响应式系统的核心功能之一,下面我们将探究 ref 函数的用法及实现原理。

使用方法

ref

ref 函数在 Vue3 中的作用是将原始值转化为响应式数据,它的用法非常简单,只需要传入一个原始值作为参数即可。

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

shallowRef

shallowRef 函数的作用与 ref 函数类似,但是它只对传入的值进行浅层响应式处理,而不会对嵌套的属性进行响应式处理。

const state = shallowRef({
  count: 0
});

// 输出 0
watchEffect(()=>console.log(state.value.count));

// 不会触发响应
state.value.count++;

triggerRef

triggerRef 函数的作用是手动触发 shallowRef 对象的响应式更新。

const state = shallowRef({
  count: 0
});

// 输出 0
watchEffect(()=>console.log(state.value.count));
state.value.count++;

// 输出 1
triggerRef(state);

customRef

customRef 函数的作用是自定义 ref 对象的响应式处理逻辑,它有两个默认参数,并返回一个带有 getset 方法的对象:

  • track:一个函数,用于追踪依赖,在 get 方法中使用。
  • trigger:一个函数,用于触发响应式更新,在 set 方法中使用。
const count = customRef((track, trigger) => {
  return {
    get() {
      track();
      //这里可以自定义get处理逻辑
      console.log("get value")
      return value;
    },
    set(newValue) {
      value = newValue;
      //这里可以自定义set处理逻辑
      console.log("set value")
      trigger();
    }
  };     
})

console.log(count.value); // 输出 get value ==> undefined
count.value = 123;
console.log(count.value); // 输出 set value ==> 123

isRef

isRef 函数接收一个参数并返回一个布尔值,用于判断该参数是否为 ref 转化的对象。

const count = ref(0);
console.log(isRef(count)); // true
console.log(isRef(123)); // false

unref

unref 函数接收一个参数并返回该参数的值,如果参数为 ref 对象,则返回该对象的值,否则返回该参数本身。

const count = ref(0);
const countValue = unref(count);
console.log(countValue); // 0

const countValue = unref(123);
console.log(countValue); // 123

toRef

toRef 函数接收两个参数,第一个参数一个响应式对象,第二个参数为属性名,返回一个 ref 对象,该对象的值与传入的对象的属性值相同。

const state = reactive({
  count: 0
});

const countRef = toRef(state, 'count');
console.log(countRef.value); // 0

countRef.value++;
console.log(state.count); // 1

toRefs

toRefs 函数接收一个对象作为参数,返回一个对象,该对象的每个属性都是 ref 对象,其值与传入对象的属性值相同。

const state = reactive({
  count: 0,
  name: 'Vue3'
});

const stateRefs = toRefs(state);
console.log(stateRefs.count.value); // 0
console.log(stateRefs.name.value); // 'Vue3'

stateRefs.count.value++;
console.log(state.count); // 1

实现原理

由于 Proxy 只能代理对象类型的数据,而对于原始类型的数据,如 numberstring 等,Proxy 无法代理,因此 Vue3 引入了 ref 函数来将原始类型的数据转化为响应式数据。

包装数据

ref 函数会将传入的原始值包装成一个带有 value 属性的对象,然后再调用 reactive 函数将这个包装对象转换为响应式数据。

以下是简化版的代码实现:

function ref(value) {
   //将传入的原始值包装成为带有value属性的对象
   const wrapper = {
      value: value
   }

   //为包装对象设置 __v_isRef 标记,表示这是一个 ref 对象
   Object.defineProperty(wrapper, '__v_isRef', {
      value: true,
      // configurable: false,
      // writable: false,
      // enumerable: false
   });

   //调用 reactive 函数将包装对象转换为响应式数据
   return reactive(wrapper);
}

由以上代码示例可以理解到为什么使用 ref 创建的响应式数据都需要使用 .value 来访问其值。

参考信息

ℹ️提示

ref相关信息