大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript
等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter
等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了常见的前端开发技术,我还擅长3D开发,熟练使用Three.js
进行3D图形绘制,并在虚拟现实与数字孪生技术上积累了丰富的经验,特别是在虚幻引擎开发方面,有着深入的理解和实践。

我一直认为技术的不断探索和实践是进步的源泉,近年来,我深入研究大数据算法的应用与发展,尤其在数据可视化和交互体验方面,取得了显著的成果。我也注重与团队的合作,能够有效地推动项目的进展和优化开发流程。现在,我担任全栈工程师,拥有CSDN博客专家认证及阿里云专家博主称号,希望通过分享我的技术心得与经验,帮助更多人提升自己的技术水平,成为更优秀的开发者。
技术qq交流群:906392632
大家好,我是小杨,一个做了6年前端的老司机。今天咱们来聊聊Vue中组件传值那些事儿,这可是Vue开发中最基础也最常用的技能之一。掌握了这些技巧,你的组件之间就能愉快地"聊天"了!
为什么需要组件传值?
想象一下,我开发了一个电商网站,商品列表组件需要把用户选中的商品信息传递给购物车组件,这就是典型的组件通信场景。Vue提供了多种传值方式,咱们一个个来看。
1. 父传子:Props大法好
这是最常用的方式,就像爸爸给儿子零花钱一样简单。
html
<!-- 父组件 -->
<template>
<div>
<child-component :money="myMoney" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: { ChildComponent },
data() {
return {
myMoney: 1000 // 这是我的私房钱
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>爸爸给了我 {{ money }} 块钱</div>
</template>
<script>
export default {
props: {
money: {
type: Number,
default: 0
}
}
}
</script>
注意点:
- Props是单向数据流,子组件不能直接修改父组件传过来的值
- 可以用
.sync
修饰符实现"双向绑定"的效果(Vue 2.x) - Vue 3中推荐用
v-model
替代.sync
2. 子传父:自定义事件
儿子要钱花,得跟爸爸打个招呼不是?
html
<!-- 子组件 -->
<template>
<button @click="askForMoney">爸,我没钱吃饭了</button>
</template>
<script>
export default {
methods: {
askForMoney() {
this.$emit('give-me-money', 200) // 触发自定义事件
}
}
}
</script>
<!-- 父组件 -->
<template>
<div>
<child-component @give-me-money="handleGiveMoney" />
<p>儿子要了 {{ givenMoney }} 块钱</p>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: { ChildComponent },
data() {
return {
givenMoney: 0
}
},
methods: {
handleGiveMoney(amount) {
this.givenMoney = amount
console.log('这小子又要钱!')
}
}
}
</script>
3. 兄弟组件通信:Event Bus
两兄弟之间直接传话,不用经过老爸了!
js
// eventBus.js
import Vue from 'vue'
export const EventBus = new Vue()
// 兄弟组件A
<script>
import { EventBus } from './eventBus'
export default {
methods: {
tellBrother() {
EventBus.$emit('message', '妈让你回家吃饭')
}
}
}
</script>
// 兄弟组件B
<script>
import { EventBus } from './eventBus'
export default {
created() {
EventBus.$on('message', (msg) => {
console.log(`哥哥说:${msg}`)
})
}
}
</script>
注意: Vue 3中因为移除了$on
等方法,推荐使用mitt等第三方库替代Event Bus。
4. Vuex:全局状态管理
家里事儿太多太乱?上个家庭管理系统!
js
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
familyMoney: 10000 // 家庭总资产
},
mutations: {
spendMoney(state, amount) {
state.familyMoney -= amount
}
},
actions: {
buySomething({ commit }, amount) {
commit('spendMoney', amount)
}
}
})
// 任意组件中使用
<script>
export default {
methods: {
buyGame() {
this.$store.dispatch('buySomething', 300)
console.log(`我偷偷花了300块买游戏,家里还剩${this.$store.state.familyMoney}`)
}
}
}
</script>
5. provide/inject:跨层级传值
爷爷直接给孙子传家宝,跳过爸爸这一辈!
html
<!-- 祖先组件 -->
<script>
export default {
provide() {
return {
familyRelic: '祖传的玉佩'
}
}
}
</script>
<!-- 后代组件(任何层级都可以) -->
<script>
export default {
inject: ['familyRelic'],
created() {
console.log(`我继承了${this.familyRelic}`) // 我继承了祖传的玉佩
}
}
</script>
6. $refs:直接访问组件实例
有时候直接"吼"一声比传纸条快
html
<template>
<child-component ref="child" />
<button @click="callChild">叫儿子</button>
</template>
<script>
export default {
methods: {
callChild() {
this.$refs.child.sayHello()
console.log('我直接调用了子组件的方法')
}
}
}
</script>
7. <math xmlns="http://www.w3.org/1998/Math/MathML"> a t t r s / attrs/ </math>attrs/listeners:高阶传值技巧
不想一层层传递props?试试这个!
html
<!-- 父组件 -->
<child-component :name="myName" :age="30" @click="handleClick" />
<!-- 中间组件 -->
<grand-child v-bind="$attrs" v-on="$listeners" />
<!-- 最终子组件 -->
<script>
export default {
created() {
console.log(this.$attrs) // { name: '小杨', age: 30 }
}
}
</script>
小杨的实战建议
- 简单场景:用props和自定义事件就够了
- 兄弟通信:小型项目用Event Bus,大型项目直接上Vuex
- 跨层级:provide/inject很方便但别滥用
- 全局状态:Vuex适合中大型项目,小项目可能杀鸡用牛刀
- 直接访问:$refs很方便,但破坏了组件封装性,慎用
记住,没有最好的方式,只有最适合的方式。我在实际项目中经常混合使用这些方法,关键是要保持代码清晰可维护。
最后说两句
组件通信就像人与人之间的交流,方式很多,重要的是选择合适的场景。刚入行时我也经常为传值问题头疼,现在回头看,其实掌握了核心原理就很简单。希望这篇分享能帮你少走弯路!