vue 父子子件传参
·
Vue 中父页面获取子页面参数(子组件数据),最常用、最简单的方式依然是 ref 引用(和之前调用子组件方法逻辑一致,无需额外语法),核心是通过 ref 获取子组件实例后,直接访问子组件的公开数据。以下分 Vue 2 和 Vue 3 给出极简实例,附带注意事项。
核心逻辑
- 父组件给子组件加
ref标识; - 父组件通过
ref获取子组件实例; - 直接访问实例上的公开参数(数据)。
一、Vue 2 实例(选项式 API)
1. 子组件(Child.vue)
定义需要被父组件访问的参数(data 中声明):
vue
<template>
<div>子组件:{{ childName }} - {{ childAge }}</div>
</template>
<script>
export default {
data() {
return {
// 子组件的公开参数(父组件可通过 ref 访问)
childName: "小明",
childAge: 18,
// 若想“私有”(不被父组件访问),可加下划线约定(仅规范,非强制)
_privateData: "我是私有数据"
};
}
};
</script>
2. 父组件(Parent.vue)
通过 this.$refs 获取子组件实例,直接访问参数:
vue
<template>
<div>
<h3>父组件</h3>
<!-- 给子组件加 ref 标识 -->
<Child ref="childRef" />
<button @click="getParentGetChildParams">获取子组件参数</button>
<p>父组件拿到的子组件名字:{{ getChildName }}</p>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
components: { Child },
data() {
return {
getChildName: "" // 存储从子组件获取的参数
};
},
methods: {
getParentGetChildParams() {
// 1. 通过 $refs 获取子组件实例
const childInstance = this.$refs.childRef;
// 2. 直接访问子组件的 data 参数
console.log("子组件名字:", childInstance.childName); // 小明
console.log("子组件年龄:", childInstance.childAge); // 18
// 3. 赋值给父组件自己的变量(用于页面展示)
this.getChildName = childInstance.childName;
// 不推荐访问“私有”参数(违反约定)
// console.log(childInstance._privateData);
}
}
};
</script>
二、Vue 3 实例(组合式 API + <script setup>)
Vue 3 的 <script setup> 中,data 变量默认是 “私有” 的,需通过 defineExpose 显式暴露给父组件(和暴露方法一致)。
1. 子组件(Child.vue)
用 defineExpose 暴露需要被父组件访问的参数:
vue
<template>
<div>Vue 3 子组件:{{ childName }} - {{ childAge }}</div>
</template>
<script setup>
import { ref } from "vue";
// 子组件的参数(ref 响应式变量)
const childName = ref("小红");
const childAge = ref(20);
// 私有变量(不暴露)
const _privateData = ref("私有数据");
// 关键:暴露参数给父组件(必须显式声明)
defineExpose({
childName,
childAge
});
</script>
2. 父组件(Parent.vue)
用 ref() 函数创建引用,访问子组件暴露的参数:
vue
<template>
<div>
<h3>Vue 3 父组件</h3>
<Child ref="childRef" />
<button @click="getParentGetChildParams">获取子组件参数</button>
<p>父组件拿到的子组件年龄:{{ getChildAge }}</p>
</div>
</template>
<script setup>
import { ref } from "vue";
import Child from "./Child.vue";
// 创建 ref 引用(和子组件 ref 标识一致)
const childRef = ref(null);
const getChildAge = ref(0); // 存储子组件参数
const getParentGetChildParams = () => {
// 1. 通过 .value 获取子组件实例(Vue 3 特性)
const childInstance = childRef.value;
if (childInstance) { // 避免子组件未挂载
// 2. 访问子组件暴露的参数(响应式变量需通过 .value 取值)
console.log("子组件名字:", childInstance.childName.value); // 小红
console.log("子组件年龄:", childInstance.childAge.value); // 20
// 3. 赋值给父组件变量(响应式同步)
getChildAge.value = childInstance.childAge.value;
// 尝试访问未暴露的参数:undefined
// console.log(childInstance._privateData);
}
};
</script>
关键注意事项
- Vue 3 必须暴露:
<script setup>中变量默认私有,父组件无法直接访问,必须用defineExpose显式暴露需要共享的参数; - 访问时机:确保子组件已挂载(如
mounted钩子后、点击事件中),否则$refs或ref.value是null(Vue 3 示例加了判断); - 响应式保持:如果子组件参数是响应式的(Vue 2 的
data、Vue 3 的ref/reactive),父组件访问时能实时同步变化(比如子组件修改childName,父组件拿到的也是最新值); - 不推荐直接修改:父组件通过
ref拿到子组件参数后,尽量只 “读” 不 “写”(如childInstance.childAge = 21),否则会破坏子组件的 “数据自治”,导致状态混乱。如果需要修改,建议通过props传递给子组件,或让子组件暴露修改方法(如setChildAge(age)); - 约定优于强制:子组件中不想被父组件访问的参数,可加下划线前缀(如
_privateData),作为规范提醒(非语法限制)。
简化场景:如果只需要 “一次性获取” 子组件参数
如果父组件不需要实时同步子组件参数,只是在某个时机(如子组件初始化完成)获取一次,可让子组件主动通过 $emit 把参数传给父组件(无需 ref),示例如下(Vue 3):
vue
<!-- 子组件(Child.vue) -->
<script setup>
import { ref, onMounted } from "vue";
const childName = ref("小兰");
const emit = defineEmits(["sendParams"]);
// 子组件挂载后,主动把参数传给父组件
onMounted(() => {
emit("sendParams", { name: childName.value, age: 22 });
});
</script>
<!-- 父组件(Parent.vue) -->
<template>
<Child @sendParams="handleChildParams" />
</template>
<script setup>
const handleChildParams = (params) => {
console.log("子组件主动传递的参数:", params); // { name: '小兰', age: 22 }
};
</script>
总结
- 最简单的方式:
ref引用 + 子组件参数暴露(Vue 2 直接访问,Vue 3 需defineExpose); - 适用场景:父组件需要实时访问子组件参数、或频繁读取子组件状态;
- 核心原则:只 “读” 不 “写”,保持子组件数据自治,避免组件耦合过重。
这种方式无需复杂语法,代码简洁,适合大多数简单场景下的父组件获取子组件参数需求。
更多推荐



所有评论(0)