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 用于控制子组件向父组件暴露的内容

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

相关推荐
云水一下15 小时前
Vue.js从零到精通系列(三):组件化基础——Props、Emits、插槽与生命周期
前端·javascript·vue.js
小糯米60115 小时前
JavaScript表达式与运算符
开发语言·javascript·ecmascript
SEO_juper15 小时前
新独立站冷启动收录全攻略:配置、推送、抓取配额优化完整手册
前端·谷歌·seo·跨境电商·外贸·geo·独立站
TinssonTai15 小时前
这个 VS Code 插件让我的 AI Coding 又快又稳 - 旧瓶装新酒
前端·人工智能·程序员
体验家15 小时前
体验家 XMPlus 网页端问卷 SDK 技术解析:用几行 JavaScript 实现精准场景触发与防打扰机制
开发语言·前端·javascript
VidDown15 小时前
VidDown 工具站:视频分辨率技术
javascript·网络·编辑器·音视频·视频编解码·视频
Maimai1080816 小时前
Web3 前端交易系统如何落地:从下单 UI 到 Operation 编码、签名与实时状态更新
前端·react.js·ui·架构·前端框架·web3
kidding72316 小时前
高效备忘清单工具类小程序
前端·计算机网络·微信小程序·小程序
IMPYLH16 小时前
HTML 的 <abbr> 元素
前端·算法·html
小鹿软件办公16 小时前
倒计时开启:Chromium 宣布几周内将全面切断 MV2 扩展支持
开发语言·javascript·ublock origin