模版引用
ref
用于注册元素或子组件的引用
在组合式 API 中,引用将存储在与名字一样的 ref
里
<template>
<p ref="myDom">hello</p>
</template>
<script lang="ts" setup>
import {
ref, onMounted } from 'vue';
const myDom = ref();
onMounted(() => {
console.log('myDom', myDom.value);
});
</script>
如果用于普通 DOM 元素,引用将是元素本身;如果用于子组件,引用将是子组件的实例
必须等组件挂载后才能访问到 ref 注册的引用
如果需要侦听一个 ref 的变化,确保考虑到其值为 undefined
的情况:
// 使用 watchEffect 监听值的变化
watchEffect(() => {
if (input.value) {
input.value.focus();
} else {
// 此时还未挂载, 或此元素已经被卸载 (例如通过 v-if 控制)
}
});
<template>
<input
type="text"
ref="input"
v-if="isShowed"
/>
<button @click="showInput">showInput</button>
</template>
<script setup lang="ts">
import {
ref, nextTick } from 'vue';
const input = ref();
const isShowed = ref(false);
const showInput = () => {
isShowed.value = true;
nextTick(() => {
// 使用 nextTick
input.value.focus(); // 确保 input 已被挂载再执行 focus()
});
};
</script>
v-for 中的模板引用
当在 v-for
中使用模板引用时,对应的 ref 值为一个数组,它将在元素被挂在后包含对应整个列表的所有元素
<template>
<ul>
<li
v-for="item in list"
ref="itemRefs"
>
{
{ item }}
</li>
</ul>
</template>
<script setup lang="ts">
import {
ref, onMounted } from 'vue';
const list = ref([1, 2, 3]);
const itemRefs = ref([]);
onMounted(() => console.log(itemRefs.value));
</script>
注意:ref 数组的顺序不保证与源数组的顺序一致
函数模板引用
ref
attribute 可以绑定一个函数,该函数会在每次组件更新时被调用- 该函数会收到元素引用作为其第 1 参数
<input :ref="(el) => { /* 将 el 赋值给一个数据属性或 ref 变量 */ }">
- 注意:这里需要使用动态的
:ref
绑定才能传入一个函数 - 当绑定的元素被卸载时,函数也会被调用一次,此时函数的第 1 参数
el
为null
组件上的 ref
模板引用也可以被用在子组件上,此时引用为组件实例
注意:使用了 <script setup>
的组件是默认私有的,父组件无法访问到使用了 <script setup>
的子组件的任何东西,除非子组件中设置了 defineExpose
宏显示暴露:
<template>
{
{ name }}
</template>
<script setup lang="ts">
import {
ref } from 'vue';
const name = ref('superman');
defineExpose({
name }); // 暴露数据
</script>
<template>
<HelloWorld ref="helloWorld" />
</template>
<script lang="ts" setup>
import HelloWorld from '@/components/HelloWorld.vue';
import {
ref, onMounted } from 'vue';
const helloWorld = ref();
onMounted(() => {
console.log('helloWorld 暴露出来的 name:', helloWorld.value.name);
});
</script>