Skip to content
此页目录
本文总阅读量

Vue Ref、reactive、toRefs、toRef、customRef 创建响应式数据

Ref

js
import { ref } from 'vue';
setup(){
  const a = ref(0); // 一般用于定义基本类型响应式, 返回 Ref 对象
  function add(){
    a.value ++;   // js 中操作数据: xxx.value,模板中则不需要
  }
  return{
    a,add
  }
}

reactive

js
let num = ref(0);
let obj = reactive({})  // 用于创建引用类型响应式
let obj = reactive({num}) // ref 会被解包 obj.num === num.value
obj.num = num       // ref 赋值给 reactive 属性也会被解包,obj.num === num.value

响应式原理

js
let obj = {
 name: 'name',
 arr: []
}
  1. target 被代理的对象
  2. handler 处理器对象,监视数据操作
js
let pro = new Proxy(obj,{
 get(target,prop){
  console.log('get方法');
  return Reflect.get(target,prop); // 读取对象的值
 },

 set(target,prop,value){
  console.log('set方法调用');
  return Reflect.set(target,prop,value); // 设置对象的值
 },

 deleteProperty(target,prop){
  console.log('delete方法调用了');
  return Reflect.deleteProperty(target,prop ); // 设置对象的值
 }
})

toRefs

js
const reactiveObj = reactive({
 num: 1,
})
// 将 reactive 对象转成 ref 对象,可用于解构
const toRefObj = toRefs(reactiveObj);
setInterval(() => {
 // reactiveObj.num ++ ;
 toRefObj.num.value++
},1000)

return {
 reactiveObj,
 ...toRefObj,
}

toRef

js
const user = reactive({
 age: 18,
 money: 20,
});

// toRef age 与 user 互通
const age = toRef(user, "age");
// ref money 与 user 不互通
const money = ref(user.money);

组件中的应用

html
<!-- 这里传入的是 age.value -->
<child :age='age'/>

<!-- child组件 -->
<template>
  <div>{{ age }}</div>
  <div>{{ length }}</div>
</template>
js
// 别人写的 hook 函数
const getLength = (age: Ref) => computed(() => age.value.toString().length);
export default defineComponent({
 name: "child",
 props: {
  age: {
   type: number,
   required: true,
  },
 },
 setup(props) {
  // 传入 props 把 age 变为 ref 对象并且同步响应
 const length = getLength(toRef(props, "age"));
  return { length };
 },
});

customRef

创建自定义的响应式

html
<input v-model="text" />
<div>{{text}}</div>
js
import {customRef} from 'vue'
const useDebouncedRef = (value, delay = 200) => {
  let timeout
  return customRef((track, trigger) => {
    get() {
      track() // 跟踪 return 出去的 value
      return value
    },
    set(newValue) {
      // 延迟后设置新的值
      clearTimeout(timeout)
      timeout = setTimeout(() => {
        value = newValue
        trigger() // 通知 vue 触发模板更新
      }, delay)
    }
  })
}

export default {
  setup() {
    return {
      text: useDebouncedRef('hello')
    }
  }
}

评论

交流群