Vue3 中的 ref、模板引用和 defineExpose 详解
一、ref 基础
在 Vue3 中,ref
是一个非常重要的响应式 API,它用于创建一个响应式的引用。
1.1 ref 的基本用法
javascript
import { ref } from 'vue';const count = ref(0); // 创建一个响应式引用,初始值为0console.log(count.value); // 访问值需要使用 .value
count.value++; // 修改值
特点:
ref
可以包装任何类型的值,使其变成响应式在 JavaScript 中访问或修改值时需要使用
.value
在模板中使用时不需要
.value
,Vue 会自动解包
1.2 为什么需要 ref
Vue3 使用 Proxy 实现响应式,但 Proxy 无法直接代理原始值(如 number, string 等)。ref
通过将这些值包装在一个对象中,解决了这个问题。
二、模板引用
模板引用是指直接在模板中访问 DOM 元素或组件实例的能力。
2.1 基本模板引用
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>
要点:
声明一个与模板中
ref
同名的响应式引用在组件挂载后,
inputRef.value
将指向 DOM 元素只能在组件挂载后访问 ref 的值
2.2 在 v-for 中使用模板引用
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
<!-- 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
<!-- Child.vue -->
<script setup>
import { ref } from 'vue';const count = ref(0);function increment() {count.value++;
}// 暴露给父组件
defineExpose({increment,count
});
</script>
现在父组件可以访问这些暴露的内容:
javascript
// 在 Parent.vue 中
onMounted(() => {childRef.value.increment(); // 调用子组件方法console.log(childRef.value.count); // 访问子组件数据
});
3.3 defineExpose 的典型用途
暴露子组件方法供父组件调用
暴露子组件状态供父组件访问
创建可复用的组件逻辑(如表单验证、对话框控制等)
四、最佳实践
命名规范:使用有意义的 ref 名称,如
formRef
,modalRef
等避免过度使用:优先考虑 props/emit 进行组件通信
null 检查:访问 ref 值前检查是否为 null
组合式函数:将 ref 逻辑封装到组合式函数中提高复用性
五、总结
ref
是 Vue3 响应式系统的核心 API 之一模板引用可以方便地访问 DOM 元素或组件实例
defineExpose
用于控制子组件向父组件暴露的内容合理使用这些特性可以创建更灵活、更易维护的组件