vue3学习记录(1)ref,isRef,shallowRef,triggerRef, customRef, 获取dom

428 阅读3分钟

对于vue3的学习其实很早之前就开始了,但是之前都是零零散散的看一些新特性,也没有刻意的系统学习,导致真正工作开发的时候好多东西要现查,这种不熟悉对开发造成了很大的困扰,所以这次师从张满月从零开始学习并记录

ref

将变量变为响应式,注意改变变量的值需要.value\color{#FF0000}注意改变变量的值需要.value,实际效果无论基本数据类型还是引用数据类型都可以通过.value来修改其值

<template lang="pug">
.content {{ boy }}
.arr {{ arr }}
.girl {{ girl }}
button(@click="change") 改变
</template>

<script setup lang="ts">
import { ref } from "vue";
import type { Ref } from "vue";

type B = {
  name: string;
  gender: string;
};

const boy = ref<B>({ name: "真嗣", gender: "man" });
const arr: Ref<Array<number>> = ref([1, 2, 3, 4]);
const girl = ref("绫波丽");

function change() {
  console.log(boy);
  boy.value.name = "初号机";
  arr.value[0] = 0;
  girl.value = "明日香";
}
</script>

点击改变按钮之前

image.png

点击改变按钮后

image.png

isRef

判断变量是否为ref对象

const boy = ref<B>({ name: "真嗣", gender: "man" });
const normal = "普通"

function change() {
  // console.log(boy);
  // boy.value.name = "初号机";
  // arr.value[0] = 0;
  // girl.value = "明日香";

  console.log(isRef(boy));
  // true

  console.log(isRef(normal));
  // false
}

shallowRef

浅层次的响应

<template lang="pug">
.content ref:{{ boy }}
.content2 shallowRef: {{ boy2 }}
button(@click="change") 改变
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef } from "vue";

const boy = ref({ name: "真嗣", gender: "man" });
const boy2 =shallowRef({ name: "真嗣", gender: "man" });
function change() {
  boy2.value.name = "初号机";
  console.log(boy2);
}
</script>

image.png

可以看到控制台的变量已经改变而视图没有改变,想要改变其值需在value这一级就赋值改变如下:

function change() {
  boy2.value.name = "初号机";
  console.log(boy2);
  boy2.value = { name: "这下改变了"}
}

注意我们上边说到shallowRef深层次赋值不会改变视图,但是当shallowRef和ref赋值同时出现时shallowRef会被影响,他的深层次赋值也会响应式的更新视图如下:

<template lang="pug">
.content ref:{{ boy }}
.content2 shallowRef: {{ boy2 }}
button(@click="change") 改变
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef } from "vue";

const boy = ref({ name: "真嗣", gender: "man" });
const boy2 = shallowRef({ name: "真嗣", gender: "man" });
function change() {
  boy.value.name = "我变了";
  boy2.value.name = "这下改变了";
}
</script>

image.png

又比如这样

<template lang="pug">
.content ref:{{ boy }}
.content2 shallowRef: {{ boy2 }}
button(@click="change") 改变
button(@click="change2") 后变
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef } from "vue";

const boy = ref({ name: "真嗣", gender: "man" });
const boy2 = shallowRef({ name: "真嗣", gender: "man" });
function change() {
  boy2.value.name = "这下改变了";
}
function change2() {
  boy.value.name = "我变了";
}
</script>

image.png

点击改变之后再点击后变 即:先调用shallowRef的赋值(深层次)再调用ref的赋值 就会导致shallowRef也会更新视图,上边在一个函数里的例子调用顺序相反也达到了相同的效果,可以看出更新视图的方法是异步的。

triggerRef

ref影响shallowRef的原因就是 triggerRef,triggerRef会在视图上强制更新我们收集到的依赖,而ref赋值时会在底层调用该方法

<template lang="pug">
.content ref:{{ boy }}
.content2 shallowRef: {{ boy2 }}
button(@click="change") 改变
button(@click="change2") 后变
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef, triggerRef } from "vue";

const boy = ref({ name: "真嗣", gender: "man" });
const boy2 = shallowRef({ name: "真嗣", gender: "man" });
function change() {
  boy2.value.name = "这下改变了";
  triggerRef(boy2);
}

image.png

customRef

自定一个ref方法,返回customRef函数 这个函数接受两个参数 一个track 一个 trigger 并返回一个对象 对象中一个get方法 一个set方法 一般get返回当前值即可也可以做想做的操作,set中接受新值一般要把新值赋给旧值,给出例子中可以在注释处调接口,并防止多次调用 做了防抖

button(@click="change") 改变
button(@click="change2") 后变
hr

div customRef:{{ cus }}
button(@click="changeCus") 改变cus
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef, triggerRef, customRef } from "vue";

const cus = myRef("旧值");
function changeCus() {
  cus.value = "新值";
}
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("触发了set方法");
          // 调接口 做防抖
          value = newVal;
          trigger();
        }, 500);
      },
    };
  });
 </script>

获取dom

注意因为setup是在created之前,还获取不到dom元素,所以这边引入onMounted勾子

<template>
.DOM(ref="dom") 我是dom
</template>

<script setup lang="ts">
import { ref, isRef, shallowRef, triggerRef, customRef, onMounted } from "vue";

const dom = ref<HTMLElement>();
onMounted(() => {
  console.log(dom.value);
});

image.png