Vue 3 模板引用(Template Refs)详解与实战示例

Vue 3 模板引用(Template Refs)详解与实战示例

引言

在 Vue 开发中,通常推荐使用 响应式数据 (refreactive) 进行数据绑定,而不是直接操作 DOM。但是,在某些情况下,我们确实需要访问某个组件或 DOM 元素,这时候就可以使用 模板引用(Template Refs)

本篇文章将详细介绍 Vue 3 的 ref 模板引用的用法、适用场景,并通过多个示例展示如何在 Vue 组件中高效操作 DOM 和组件实例。


1. 什么是 Vue 模板引用?

模板引用(Template Refs) 允许我们在 Vue 组件的模板中标记一个 DOM 元素或子组件,并在 setup 选项中访问它。

基本语法

html 复制代码
<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 渲染完成后可用

2. 模板引用的使用场景

✅ 操作原生 DOM

当我们需要手动操作 DOM 时,如获取元素的宽高、设置焦点等:

html 复制代码
<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 访问子组件的方法和数据:

html 复制代码
<!-- 子组件 (Child.vue) -->
<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>
html 复制代码
<!-- 父组件 -->
<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 公开组件方法,否则父组件无法访问。


3. 使用 ref 访问多个元素

当我们需要访问 多个 DOM 元素时,可以使用 ref 结合 v-for

html 复制代码
<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 之后才填充值。


4. 访问 setup() 之外的数据

如果你在 setup() 之外使用 ref,可以通过 getCurrentInstance() 获取 Vue 实例:

html 复制代码
<script setup>
import { getCurrentInstance, onMounted } from 'vue';

onMounted(() => {
  const instance = getCurrentInstance();
  console.log(instance.refs); // 访问 ref
});
</script>

5. 结论

Vue 3 的 模板引用(Template Refs) 让我们可以更方便地访问 DOM 和子组件实例,适用于:

  • 操作原生 DOM(如获取焦点、测量元素尺寸)
  • 调用子组件方法 (通过 refdefineExpose
  • 获取多个元素 (使用 ref 数组)

但是 ,如果能用 Vue 的 响应式数据 来实现同样的效果,最好避免直接操作 DOM,以保持 Vue 响应式系统的优势。

相关推荐
方也_arkling32 分钟前
别名路径联想提示。@/统一文件路径的配置
前端·javascript
毕设源码-朱学姐35 分钟前
【开题答辩全过程】以 基于web教师继续教育系统的设计与实现为例,包含答辩的问题和答案
前端
qq_1777673740 分钟前
React Native鸿蒙跨平台剧集管理应用实现,包含主应用组件、剧集列表、分类筛选、搜索排序等功能模块
javascript·react native·react.js·交互·harmonyos
qq_177767371 小时前
React Native鸿蒙跨平台自定义复选框组件,通过样式数组实现选中/未选中状态的样式切换,使用链式调用替代样式数组,实现状态驱动的样式变化
javascript·react native·react.js·架构·ecmascript·harmonyos·媒体
web打印社区1 小时前
web-print-pdf:突破浏览器限制,实现专业级Web静默打印
前端·javascript·vue.js·electron·html
RFCEO1 小时前
前端编程 课程十三、:CSS核心基础1:CSS选择器
前端·css·css基础选择器详细教程·css类选择器使用方法·css类选择器命名规范·css后代选择器·精准选中嵌套元素
烬头88212 小时前
React Native鸿蒙跨平台采用了函数式组件的形式,通过 props 接收分类数据,使用 TouchableOpacity实现了点击交互效果
javascript·react native·react.js·ecmascript·交互·harmonyos
Amumu121382 小时前
Vuex介绍
前端·javascript·vue.js
We་ct2 小时前
LeetCode 54. 螺旋矩阵:两种解法吃透顺时针遍历逻辑
前端·算法·leetcode·矩阵·typescript
2601_949809592 小时前
flutter_for_openharmony家庭相册app实战+相册详情实现
javascript·flutter·ajax