Vue3 中的 ref、模板引用和 defineExpose 详解

一、ref 基础

在 Vue3 中,ref 是一个非常重要的响应式 API,它用于创建一个响应式的引用。

1.1 ref 的基本用法

javascript

javascript 复制代码
import { ref } from 'vue';

const count = ref(0); // 创建一个响应式引用,初始值为0

console.log(count.value); // 访问值需要使用 .value
count.value++; // 修改值

特点:

  • ref 可以包装任何类型的值,使其变成响应式

  • 在 JavaScript 中访问或修改值时需要使用 .value

  • 在模板中使用时不需要 .value,Vue 会自动解包

1.2 为什么需要 ref

Vue3 使用 Proxy 实现响应式,但 Proxy 无法直接代理原始值(如 number, string 等)。ref 通过将这些值包装在一个对象中,解决了这个问题。

二、模板引用

模板引用是指直接在模板中访问 DOM 元素或组件实例的能力。

2.1 基本模板引用

html

html 复制代码
<template>
  <input ref="inputRef" type="text" />
</template>

<script setup>
import { ref, onMounted } from 'vue';

const inputRef = ref(null); // 必须与模板中的 ref 同名

onMounted(() => {
  inputRef.value.focus(); // 在挂载后自动聚焦
});
</script>

要点:

  1. 声明一个与模板中 ref 同名的响应式引用

  2. 在组件挂载后,inputRef.value 将指向 DOM 元素

  3. 只能在组件挂载后访问 ref 的值

2.2 在 v-for 中使用模板引用

html

html 复制代码
<template>
  <ul>
    <li v-for="item in list" :key="item.id" ref="itemRefs">
      {{ item.text }}
    </li>
  </ul>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const list = ref([
  { id: 1, text: 'Item 1' },
  { id: 2, text: 'Item 2' }
]);

const itemRefs = ref([]);

onMounted(() => {
  console.log(itemRefs.value); // 包含所有 li 元素的数组
});
</script>

注意: 在 v-for 中使用 ref 时,ref 的值将是一个包含所有元素的数组。

三、组件引用与 defineExpose

3.1 引用子组件

html

html 复制代码
<!-- Parent.vue -->
<template>
  <Child ref="childRef" />
</template>

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

const childRef = ref(null);

onMounted(() => {
  console.log(childRef.value); // 子组件实例
});
</script>

3.2 使用 defineExpose 暴露组件方法

默认情况下,使用 <script setup> 的组件是封闭的 ,父组件无法访问子组件的任何内容。需要使用 defineExpose 显式暴露:

html

html 复制代码
<!-- Child.vue -->
<script setup>
import { ref } from 'vue';

const count = ref(0);

function increment() {
  count.value++;
}

// 暴露给父组件
defineExpose({
  increment,
  count
});
</script>

现在父组件可以访问这些暴露的内容:

javascript

javascript 复制代码
// 在 Parent.vue 中
onMounted(() => {
  childRef.value.increment(); // 调用子组件方法
  console.log(childRef.value.count); // 访问子组件数据
});

3.3 defineExpose 的典型用途

  1. 暴露子组件方法供父组件调用

  2. 暴露子组件状态供父组件访问

  3. 创建可复用的组件逻辑(如表单验证、对话框控制等)

四、最佳实践

  1. 命名规范 :使用有意义的 ref 名称,如 formRef, modalRef

  2. 避免过度使用:优先考虑 props/emit 进行组件通信

  3. null 检查:访问 ref 值前检查是否为 null

  4. 组合式函数:将 ref 逻辑封装到组合式函数中提高复用性

五、总结

  • ref 是 Vue3 响应式系统的核心 API 之一

  • 模板引用可以方便地访问 DOM 元素或组件实例

  • defineExpose 用于控制子组件向父组件暴露的内容

  • 合理使用这些特性可以创建更灵活、更易维护的组件

相关推荐
困惑阿三16 分钟前
React 展示Markdown内容
前端·react.js·前端框架
lichong9511 小时前
【大前端++】Android studio Log日志高对比度配色方案
android·java·前端·json·android studio·大前端·大前端++
没头脑的男大1 小时前
如何把pdf转换的excell多个表格合并
java·前端·pdf
妄小闲1 小时前
html网站模板 html网页设计模板源码网站
前端·html
Restart-AHTCM2 小时前
前端核心框架vue之(路由篇3/5)
前端·javascript·vue.js
段振轩2 小时前
Docker nginx容器部署前端项目。
前端·nginx·docker
让时光到此为止。2 小时前
vue的首屏优化是怎么做的
前端·javascript·vue.js
San303 小时前
JavaScript 流程控制与数组操作全解析:从条件判断到数据高效处理
javascript·面试·代码规范
温宇飞3 小时前
CSS 中如何处理空白字符
前端
dengzhenyue3 小时前
矩形碰撞检测
开发语言·前端·javascript