在 Vue 开发中,通常推荐使用 响应式数据 (ref
和 reactive
) 进行数据绑定,而不是直接操作 DOM。但是,在某些情况下,我们确实需要访问某个组件或 DOM 元素,这时候就可以使用 模板引用(Template Refs)。
本篇文章将详细介绍 Vue 3 的 ref
模板引用的用法、适用场景,并通过多个示例展示如何在 Vue 组件中高效操作 DOM 和组件实例。
模板引用(Template Refs) 允许我们在 Vue 组件的模板中标记一个 DOM 元素或子组件,并在 setup
选项中访问它。
<template>
<div ref="myDiv">Hello Vue!div>
template>
<script setup>
import { ref, onMounted } from 'vue';
const myDiv = ref(null); // 定义模板引用
onMounted(() => {
console.log(myDiv.value); // 获取 DOM 元素
});
script>
说明:
ref="myDiv"
绑定到myDiv
变量onMounted
钩子确保myDiv.value
在 DOM 渲染完成后可用
当我们需要手动操作 DOM 时,如获取元素的宽高、设置焦点等:
<template>
<input ref="inputRef" type="text" placeholder="输入内容">
<button @click="focusInput">聚焦输入框button>
template>
<script setup>
import { ref } from 'vue';
const inputRef = ref(null);
const focusInput = () => {
inputRef.value.focus(); // 手动聚焦输入框
};
script>
可以使用 ref
访问子组件的方法和数据:
<template>
<div>子组件div>
template>
<script setup>
import { ref } from 'vue';
const message = ref("Hello from Child Component!");
const sayHello = () => {
console.log(message.value);
};
defineExpose({ sayHello }); // 允许父组件访问 `sayHello`
script>
<template>
<Child ref="childRef" />
<button @click="callChildMethod">调用子组件方法button>
template>
<script setup>
import { ref, onMounted } from 'vue';
import Child from './Child.vue';
const childRef = ref(null);
onMounted(() => {
console.log(childRef.value); // 获取子组件实例
});
const callChildMethod = () => {
childRef.value.sayHello(); // 调用子组件方法
};
script>
defineExpose
:Vue 3 需要使用defineExpose
公开组件方法,否则父组件无法访问。
ref
访问多个元素当我们需要访问 多个 DOM 元素时,可以使用 ref
结合 v-for
:
<template>
<div v-for="(item, index) in list" :key="index" ref="itemRefs">
{{ item }}
div>
<button @click="logElements">查看所有元素button>
template>
<script setup>
import { ref, onMounted } from 'vue';
const list = ref(["Vue", "React", "Angular"]);
const itemRefs = ref([]); // 存储多个 DOM 元素
onMounted(() => {
console.log(itemRefs.value); // 所有 div 的 DOM 元素
});
const logElements = () => {
itemRefs.value.forEach(el => console.log(el.textContent));
};
script>
注意:
ref
数组会在onMounted
之后才填充值。
setup()
之外的数据如果你在 setup()
之外使用 ref
,可以通过 getCurrentInstance()
获取 Vue 实例:
<script setup>
import { getCurrentInstance, onMounted } from 'vue';
onMounted(() => {
const instance = getCurrentInstance();
console.log(instance.refs); // 访问 ref
});
script>
Vue 3 的 模板引用(Template Refs) 让我们可以更方便地访问 DOM 和子组件实例,适用于:
ref
和 defineExpose
)ref
数组)但是,如果能用 Vue 的 响应式数据 来实现同样的效果,最好避免直接操作 DOM,以保持 Vue 响应式系统的优势。