🎯 场景目标
想在父组件中 访问子组件里的 DOM 元素,比如获取 <button> 标签本身。
✅ 第一步:在子组件中定义 ref 并暴露出去
子组件(MyButton.vue)
<template>
<button ref="buttonRef">按钮</button>
</template>
<script setup lang="ts">
import { ref } from "vue";
// 1️⃣ 创建 ref,用于绑定 DOM 元素
const buttonRef = ref<HTMLButtonElement | null>(null);
// 2️⃣ 暴露这个 ref 给父组件用
defineExpose({
buttonRef,
});
</script>
✅
buttonRef是一个响应式引用,指向<button>这个真实 DOM 元素。
✅defineExpose()是 Vue3<script setup>提供的语法,用来暴露子组件内部的属性给父组件访问。
✅ 第二步:在父组件中通过 ref 获取子组件实例
父组件(App.vue 或其他)
<template>
<!-- 3️⃣ 给子组件加 ref -->
<MyButton ref="btnRef" />
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import MyButton from "@/components/Button/MyButton.vue";
// 4️⃣ 创建 ref,用来接收子组件实例
const btnRef = ref<InstanceType<typeof MyButton> | null>(null);
// 5️⃣ 组件挂载后访问子组件暴露的 DOM 元素
onMounted(() => {
const dom = btnRef.value?.buttonRef; // ✅ 注意这里没有 `.value`,因为暴露出来的已经是 HTMLButtonElement
console.log("子组件内部的 button DOM:", dom);
});
</script>
📌 小结步骤回顾
| 步骤 | 操作 | 说明 |
|---|---|---|
| 1️⃣ | 子组件中创建 ref 指向 DOM | ref<HTMLButtonElement>() |
| 2️⃣ | 用 defineExpose 暴露 ref | 使父组件能访问 |
| 3️⃣ | 父组件中给子组件加 ref | <MyButton ref="btnRef" /> |
| 4️⃣ | 在 onMounted 中访问 btnRef.value?.buttonRef | 得到原生 DOM 元素 |
🧠 小Tips
ref()创建的是一个响应式引用对象,它有.value属性。- 但当你通过
defineExpose()暴露出去时,可以直接访问,不需要.value.value。 InstanceType<typeof Component>是 TS 写法,拿到组件的类型实例。