Vue 中父页面获取子页面参数(子组件数据),最常用、最简单的方式依然是 ref 引用(和之前调用子组件方法逻辑一致,无需额外语法),核心是通过 ref 获取子组件实例后,直接访问子组件的公开数据。以下分 Vue 2 和 Vue 3 给出极简实例,附带注意事项。

核心逻辑

  1. 父组件给子组件加 ref 标识;
  2. 父组件通过 ref 获取子组件实例;
  3. 直接访问实例上的公开参数(数据)。

一、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>

关键注意事项

  1. Vue 3 必须暴露<script setup> 中变量默认私有,父组件无法直接访问,必须用 defineExpose 显式暴露需要共享的参数;
  2. 访问时机:确保子组件已挂载(如 mounted 钩子后、点击事件中),否则 $refs 或 ref.value 是 null(Vue 3 示例加了判断);
  3. 响应式保持:如果子组件参数是响应式的(Vue 2 的 data、Vue 3 的 ref/reactive),父组件访问时能实时同步变化(比如子组件修改 childName,父组件拿到的也是最新值);
  4. 不推荐直接修改:父组件通过 ref 拿到子组件参数后,尽量只 “读” 不 “写”(如 childInstance.childAge = 21),否则会破坏子组件的 “数据自治”,导致状态混乱。如果需要修改,建议通过 props 传递给子组件,或让子组件暴露修改方法(如 setChildAge(age));
  5. 约定优于强制:子组件中不想被父组件访问的参数,可加下划线前缀(如 _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);
  • 适用场景:父组件需要实时访问子组件参数、或频繁读取子组件状态;
  • 核心原则:只 “读” 不 “写”,保持子组件数据自治,避免组件耦合过重。

这种方式无需复杂语法,代码简洁,适合大多数简单场景下的父组件获取子组件参数需求。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐