You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue中父组件如何访问单文件子组件数据?已尝试$emit未成功

别慌!我给你几个简单到上手就能用的方案,完美解决Vue单文件组件间的数据访问问题,先从最常见的场景说起:

一、如果是父子组件之间传值(90%的场景都是这个)

1. 父组件 → 子组件:用 props 直接传

这是Vue官方推荐的父传子方式,简单明了。比如父组件里有个初始为空的输入框数据,要传给子组件展示:

父组件代码:

<template>
  <div>
    <!-- 用`:属性名`把父组件的inputValue传给子组件 -->
    <ChildComponent :child-value="inputValue" />
    <!-- 输入框绑定父组件的数据,实时修改 -->
    <input v-model="inputValue" placeholder="输入内容试试" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      inputValue: '' // 初始为空的字符串
    }
  }
}
</script>

子组件代码:

<template>
  <div>子组件拿到的值:{{ childValue }}</div>
</template>

<script>
export default {
  // 声明接收父组件传过来的props,还可以指定类型和默认值
  props: {
    childValue: {
      type: String,
      default: ''
    }
  }
}
</script>

2. 子组件 → 父组件:正确使用 $emit(你之前大概率没写对监听步骤)

如果是子组件里的输入框修改数据,要把值传给父组件,$emit是标准做法,但必须让父组件监听事件才能拿到数据,这可能是你之前失败的原因!

子组件代码:

<template>
  <div>
    <!-- 输入框绑定子组件自己的内部数据 -->
    <input v-model="childInput" @input="sendToParent" placeholder="子组件输入内容" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      childInput: ''
    }
  },
  methods: {
    sendToParent() {
      // 第一个参数是自定义事件名,第二个是要传递的数据
      this.$emit('update-parent-value', this.childInput)
    }
  }
}
</script>

父组件代码:

<template>
  <div>
    <!-- 监听子组件触发的自定义事件,用方法接收数据 -->
    <ChildComponent @update-parent-value="handleValueUpdate" />
    <p>父组件拿到子组件的值:{{ parentValue }}</p>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      parentValue: ''
    }
  },
  methods: {
    handleValueUpdate(value) {
      // 把传过来的数据赋值给父组件的变量
      this.parentValue = value
    }
  }
}
</script>

小提醒:Vue里自定义事件名建议用短横线分隔(比如update-parent-value),避免大小写敏感的问题。

二、如果是非父子组件(比如兄弟组件、跨多层级组件):用轻量的事件总线

如果组件之间没有直接的父子关系,用事件总线是最简单的方案,不用引入复杂的状态管理工具:

Vue2 版本(原生支持事件总线)

  1. 在main.js里全局注册一个总线实例:
import Vue from 'vue'
// 把总线挂载到Vue原型上,所有组件都能访问
Vue.prototype.$bus = new Vue()
  1. 发送数据的组件(比如ComponentA):
<template>
  <input v-model="inputValue" @input="sendData" />
</template>

<script>
export default {
  data() {
    return {
      inputValue: ''
    }
  },
  methods: {
    sendData() {
      // 触发总线事件,传递数据
      this.$bus.$emit('share-data', this.inputValue)
    }
  }
}
</script>
  1. 接收数据的组件(比如ComponentB):
<template>
  <p>共享的数据:{{ sharedValue }}</p>
</template>

<script>
export default {
  data() {
    return {
      sharedValue: ''
    }
  },
  mounted() {
    // 监听总线事件,接收数据
    this.$bus.$on('share-data', (value) => {
      this.sharedValue = value
    })
  },
  beforeDestroy() {
    // 组件销毁时取消监听,防止内存泄漏
    this.$bus.$off('share-data')
  }
}
</script>

Vue3 版本(用mitt库替代原生事件)

Vue3移除了$on/$off方法,所以用轻量的mitt库(只有200B左右):

  1. 先安装:npm install mitt
  2. 创建一个bus.js文件:
import mitt from 'mitt'
// 创建并导出总线实例
export const bus = mitt()
  1. 发送数据的组件:
<template>
  <input v-model="inputValue" @input="sendData" />
</template>

<script setup>
import { ref } from 'vue'
import { bus } from './bus.js'

const inputValue = ref('')

const sendData = () => {
  // 触发事件传递数据
  bus.emit('share-data', inputValue.value)
}
</script>
  1. 接收数据的组件:
<template>
  <p>共享的数据:{{ sharedValue }}</p>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { bus } from './bus.js'

const sharedValue = ref('')

onMounted(() => {
  // 监听事件接收数据
  bus.on('share-data', (value) => {
    sharedValue.value = value
  })
})

onUnmounted(() => {
  // 销毁时取消监听
  bus.off('share-data')
})
</script>

这些方案都是最基础也最容易理解的,你可以根据自己的组件关系选对应的方法,要是还有具体代码的问题,随时贴出来细化!

内容的提问来源于stack exchange,提问作者user9046370

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:59:34