快速入门Vue模板引用:从收DOM“快递”到调子组件方法,你玩明白了吗?


url: /posts/ddbce4f2a23aa72c96b1c0473900321e/
title: 快速入门Vue模板引用:从收DOM“快递”到调子组件方法,你玩明白了吗?
date: 2025-11-03T02:55:45+08:00
lastmod: 2025-11-03T02:55:45+08:00
author: cmdragon

summary:
Vue中的模板引用(Template Refs)用于在声明式编程中直接操作DOM或访问子组件实例。通过ref属性标记元素或组件,并在setup中使用同名响应式变量访问。子组件需通过defineExpose暴露内部方法或属性供父组件调用。操作DOM时,应在onMountednextTick中确保DOM已渲染。常见应用包括自动聚焦输入框、集成第三方库和动态获取元素尺寸。

categories:

  • vue

tags:

  • 基础入门
    • Vue
  • 模板引用
  • DOM操作
  • 组件通信
  • nextTick
  • defineExpose
  • 最佳实践

cmdragon_cn.png

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

发现1000+提升效率与开发的AI工具和实用程序:https://tools.cmdragon.cn/

一、模板引用的基本概念与用法

在Vue的声明式编程模型中,我们通常不需要直接操作DOM——Vue会根据数据自动更新视图。但有些场景必须直接接触DOM:比如聚焦输入框、获取元素尺寸、集成第三方DOM库(如Chart.js)。这时候,**模板引用(Template Refs)**就成了连接声明式世界与命令式DOM操作的桥梁。

1.1 什么是模板引用?

模板引用是Vue提供的一种标记DOM元素或组件的方式:通过给元素或组件添加ref属性(类似“标签”),我们可以在setup中通过同名的响应式变量,直接访问对应的DOM元素或组件实例。

1.2 如何声明和使用模板引用?

使用模板引用的步骤非常简单,只需两步:

  1. 在模板中标记元素:给需要引用的元素添加ref="xxx"属性;
  2. setup中创建响应式变量:用ref(null)创建同名变量,Vue会自动将DOM元素赋值给它。

注意:模板引用的变量必须用ref(null)初始化(初始值为null),因为Vue会在组件挂载后才将DOM元素赋值给它。

1.3 示例:自动聚焦输入框

下面是一个最常见的场景——页面加载后自动聚焦输入框:

<template>
  <!-- 用ref标记输入框 -->
  <input ref="inputRef" type="text" placeholder="请输入内容" />
</template>

<script setup>
// 1. 导入需要的API:ref(创建响应式变量)、onMounted(生命周期钩子)
import { ref, onMounted } from 'vue'

// 2. 创建响应式变量,初始值为null(此时DOM还未渲染)
const inputRef = ref(null)

// 3. 组件挂载后(DOM已渲染),聚焦输入框
onMounted(() => {
  // inputRef.value 此时指向模板中的<input>元素
  inputRef.value.focus() 
})
</script>

代码解释

  • ref="inputRef":给输入框贴了个“标签”,告诉Vue“我要引用这个元素”;
  • const inputRef = ref(null):在setup中创建一个“容器”,等待Vue把DOM元素装进来;
  • onMounted:组件挂载完成的生命周期钩子,此时DOM已经渲染完成,inputRef.value不再是null,可以安全调用focus()方法。

二、组件的模板引用与暴露

模板引用不仅能标记DOM元素,还能标记子组件。但组件的引用有个特殊规则:默认情况下,子组件的内部状态和方法是“私有的”,父组件无法直接访问。如果要让父组件调用子组件的方法或访问其内部元素,必须用defineExpose显式暴露。

2.1 引用子组件的默认行为

当你给子组件添加ref属性时,父组件拿到的是子组件的根元素(如果子组件有多个根元素,会报错)。比如:

<!-- ParentComponent.vue -->
<template>
  <!-- 引用子组件 -->
  <ChildComponent ref="childRef" />
</template>

<script setup>
import { ref, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'

const childRef = ref(null)

onMounted(() => {
  // childRef.value 指向子组件的根元素(比如<div>)
  console.log(childRef.value) 
})
</script>
2.2 暴露子组件内部内容:defineExpose

如果父组件需要访问子组件的内部方法或非根元素,子组件必须用defineExpose将这些内容“公开”。defineExpose是Vue 3的内置API,专门用于暴露setup中的内容给父组件。

2.3 示例:父组件调用子组件的方法

假设子组件有一个“点击按钮”的方法,父组件需要直接调用它:

子组件(ChildComponent.vue)

<template>
  <button @click="handleClick">子组件按钮</button>
</template>

<script setup>
// 导入defineExpose API
import { defineExpose } from 'vue'

// 子组件的内部方法
const handleClick = () => {
  console.log('子组件按钮被点击!')
}

// 关键:将handleClick方法暴露给父组件
defineExpose({
  handleClick
})
</script>

父组件(ParentComponent.vue)

<template>
  <ChildComponent ref="childRef" />
  <button @click="callChildMethod">调用子组件方法</button>
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

// 引用子组件实例
const childRef = ref(null)

// 父组件调用子组件方法
const callChildMethod = () => {
  // 通过childRef.value访问子组件暴露的handleClick
  childRef.value.handleClick() 
}
</script>

效果:点击父组件的“调用子组件方法”按钮,会触发子组件的handleClick,控制台输出“子组件按钮被点击!”。

三、DOM操作的最佳实践

直接操作DOM虽然灵活,但容易破坏Vue的响应式流程。以下是避免踩坑的关键原则

3.1 何时可以安全操作DOM?

DOM元素只有在组件挂载后才会存在,因此:

  • 不要在setup的顶级 scope 直接访问模板引用(此时xxx.value还是null);
  • 不要在onBeforeMount钩子中操作DOM(组件还没挂载,元素未渲染);
  • 安全时机onMounted钩子(组件首次挂载完成)、nextTick(DOM更新后)。
3.2 nextTick:处理DOM更新后的操作

Vue的DOM更新是

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值