Vue3中通过ref注册模版引用,你的类型会丢失吗?

159 阅读1分钟

前言:

在日常开发中,我们通过ref获取组件实例,从而执行其内部的方法,这样的操作很常见。但是其获取的实例我们无法确定其类型,本文围绕这个主题展开讲一下,高手请略过。

通过阅读本文,可以学习到如下知识点:

  • Vue内置类型InstanceType
  • useTemplateRef

示例:

子组件如下:

// Comp.vue
<template>
  count:{{countRef}} 
  <button @click="add">+</button>
</template>

<script lang="ts" setup>
import {ref} from "vue";
const countRef = ref(0);
function add(){
  countRef.value ++;
}
defineExpose({add});
</script>

当我们在父组件使用的时候,想要执行其内部的方法

// Index.vue中
<template>
  <Comp ref="compRef"></Comp>
  <button @click="handleClick">click me!</button>
</template>
<script setup lang="ts">
import { ref} from 'vue';
import Comp from './Comp.vue';

const compRef = ref(null);

function handleClick(){
  compRef.value.handleAdd();
}
</script>

但是,此时compRef的类型是any,我们根本不知道当前获取的组件实例上有什么方法。

image.png 我们可以通过Vue中内置的类型InstanceType进行标注,从而获得类型提示。我们将代码按照如下修改:


<script setup lang="ts">
import { Ref, ref} from 'vue';
import Comp from './components/Comp.vue';

type compType = InstanceType<typeof Comp>;

const compRef:Ref<compType|null> = ref(null);

function handleClick(){
  compRef.value?.handleAdd();
}
</script>

注意:如果你的子组件是使用setup实现的,那么一定要定义defineExpose进行导出, 但是尽管现在类型已经支持,但是vue注册模版通过定义一个变量,就能与组件实例绑定的这种操作,在网上也是备受争议,所以在vue3.5以后的版本里面给我们提供了一个新的API:useTemplateRef,使其操作更符合正常的思维逻辑,不再那么突兀。

<script setup lang="ts">
import { useTemplateRef } from 'vue';
import Comp from './components/Comp.vue';

type compType = InstanceType<typeof Comp>;

const compRef = useTemplateRef<compType>("compRef");

function handleClick(){
  compRef.value?.handleAdd();
}
</script>