Ref全家桶

由于ref返回的是一个ES6的class类,要修改ref的值要通过.value来进行修改。

isRef

用于判断是不是ref,用法为

vue
12345
<script setup>
import { isRef, ref } from 'vue';
const Cain = ref({name: "Cain"})
isRef(Cain)//返回一个布尔值
</script>

shallowRef

ref实现深层次的响应,shallowRef实现浅层的响应

vue
1234567891011121314151617
<template>
  <button @click="change" style="width: 200px;height: 200px;">修改</button>
  <div>
    <h1>ref:{{ Cain }}</h1>
    <h1>shallowRef:{{ Cain2 }}</h1>
  </div>
</template>

<script setup>
import { ref, shallowRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });
const change = () => {
  Cain2.value.name = "Cain3";
  console.log(Cain2);
};
</script>

点击按钮前,视图效果如下:

3d2e194d0e5a71e617e04ab795bfd14c.png

点击按钮后,视图效果没有变化,控制台输出:

e298011cd3157fcaed7b912d1f29b36b.png

说明值变化了,但是视窗没有变化,这是因为shallowRef的响应是浅层的,shallowRef的响应只到.value处,如果要实现修改shallowRef的效果需要直接修改.value

vue
123456789
<script setup>
import { ref, shallowRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });
const change = () => {
  Cain2.value = { name: "Cain3" };//修改成这样就可以实现响应了
  console.log(Cain2);
};
</script>

视窗显示:

b4e08b8c53c44605ac35cc6583389b77.png

可以看到视图成功响应了,但是有一个地方需要注意就是如果ref跟shallowRef写到一起就会引起shallowRef跟ref一起变化

vue
12345678910111213
<script setup>
import { ref, shallowRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });
    
//如果这样写的话shallowRef就会被ref影响到改变
const change = () => {
  Cain.value.name = "我是ref"
  Cain2.value.name = "我被影响了";
  console.log(Cain2);
};
    
</script>

6ec7e73d0ece78b804cb7ab5c260f1de.png

这是因为ref更新底层会调用triggerRef

vue
123456789101112
<script setup>
import { ref, shallowRef, triggerRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });

//如果这样写的话shallowRef也会更新
const change = () => {
  Cain2.value.name = "我被影响了";
  triggerRef(Cain2)
  console.log(Cain2);
};
</script>

效果如下:

e11bb70b80af96a766ebb4bc1ae42c9b.png

customRef

用于自己实现ref功能,但是可以在ref更新过程中加入一些自己的逻辑,例如防抖,下面是自己实现一个最简易的ref代码

vue
123456789101112131415161718192021222324
<script setup lang="ts">
import { customRef, ref, shallowRef, triggerRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });
//实现一个最基础的ref
function MyRef<T>(value: T) {
  return customRef((track, trigger) => {
    return {
      get(){
        track()//收集依赖
        return value
      },
      set(newVal){
        value = newVal
        trigger()//更新依赖
      }
    }
  })
}
const myRef = MyRef<string>("myCain")
const change = () => {
  myRef.value = "我被修改了"
}
</script>

以下是最简单的防抖功能实现

vue
123456789101112131415161718192021222324252627282930
<script setup lang="ts">
import { customRef, ref, shallowRef, triggerRef } from "vue";
const Cain = ref({ name: "Cain" });
const Cain2 = shallowRef({ name: "Cain2" });
//实现一个最基础的防抖
function MyRef<T>(value: T) {
  let timer: any;
  return customRef((track, trigger) => {
    return {
      get() {
        track(); //收集依赖
        return value;
      },
      set(newVal) {
        clearTimeout(timer);
        timer =  setTimeout(() => {
          console.log("调用了接口")
          timer = null
          value = newVal;
          trigger(); //更新依赖
        },500);
      },
    };
  });
}
const myRef = MyRef<string>("myCain");
const change = () => {
  myRef.value = "我被修改了";
};
</script>