Vue 组件间通信的方式有哪些?
本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Tair(兼容Redis),内存型 2GB
云数据库 RDS MySQL,集群系列 2核4GB
简介:
Vue组件间通信主要通过Props、Events、Provide/Inject、Vuex(状态管理)、Ref、Event Bus等实现,支持父子组件及跨级组件间的高效数据传递与状态共享。
- Props / $emit(父子组件通信)
- Props(属性传递):
- 父组件可以通过
props
将数据传递给子组件。在子组件中,通过props
选项来接收父组件传递的数据。例如,父组件中有一个数据message
,在子组件的props
中定义接收这个数据的属性名,就可以在子组件中使用这个数据。
- 示例:
- 父组件:
<template>
<div>
<child-component :message="parentMessage"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
parentMessage: '这是来自父组件的消息'
};
}
};
</script>
- 子组件:
<template>
<div>{
{ message }}</div>
</template>
<script>
export default {
props: ['message']
};
</script>
- $emit(事件触发):
- 子组件可以通过
$emit
方法来触发一个自定义事件,并将数据传递给父组件。父组件可以通过在子组件标签上监听这个自定义事件来接收数据。
- 示例:
- 子组件:
<template>
<button @click="sendMessage">发送消息给父组件</button>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$emit('childMessage', '这是来自子组件的消息');
}
}
};
</script>
- 父组件:
<template>
<div>
<child-component @childMessage="handleChildMessage"></child-component>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
handleChildMessage(message) {
console.log(message);
}
}
};
</script>
- 事件总线(Event Bus)(非父子组件通信)
- 可以创建一个独立于组件树之外的事件中心(
Vue
实例),用于在不同组件之间传递消息。组件可以通过在这个事件中心上监听和触发事件来进行通信。
- 示例:
- 创建事件总线(通常在一个单独的
js
文件中):import Vue from 'vue';
export const eventBus = new Vue();
- 组件A发送事件:
<template>
<button @click="sendMessage">发送消息</button>
</template>
<script>
import {
eventBus } from './event - bus.js';
export default {
methods: {
sendMessage() {
eventBus.$emit('message', '这是来自组件A的消息');
}
}
};
</script>
- 组件B接收事件:
<template>
<div>等待接收消息</div>
</template>
<script>
import {
eventBus } from './event - bus.js';
export default {
mounted() {
eventBus.$on('message', (message) => {
console.log(message);
});
}
};
</script>
- Vuex(状态管理,适用于复杂的组件间通信)
- 状态(State):
- 用于存储应用的状态,所有组件可以访问这个状态。例如,在一个电商应用中,商品列表的数据可以存储在
Vuex
的状态中。
- Mutations(同步操作):
- 是唯一可以修改
Vuex
状态的地方,必须是同步函数。例如,通过一个mutation
来添加商品到购物车状态中。
- Actions(异步操作):
- 用于处理异步操作,比如从服务器获取数据,然后通过
commit
方法触发mutations
来更新状态。
- Getters(计算属性):
- 类似于组件中的计算属性,用于从状态中派生出一些数据,方便组件获取。
- 示例:
- 安装
Vuex
并创建store
文件(store.js
):import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync({
commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
},
getters: {
doubleCount(state) {
return state.count * 2;
}
}
});
export default store;
- 在组件中使用
Vuex
:<template>
<div>
<p>计数:{
{ count }}</p>
<button @click="increment">增加计数</button>
<button @click="incrementAsync">异步增加计数</button>
</div>
</template>
<script>
import {
mapState, mapMutations, mapActions, mapGetters } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapMutations(['increment']),
...mapActions(['incrementAsync'])
}
};
</script>
- Provide / Inject(祖孙组件通信)
- Provide(提供数据):
- 父组件可以通过
provide
选项来提供数据,这些数据可以被它的子孙组件访问。
- Inject(注入数据):
- 子孙组件可以通过
inject
选项来注入由父组件提供的数据。
- 示例:
- 父组件:
<template>
<div>
<grand - child - component></grand - child - component>
</div>
</template>
<script>
import GrandChildComponent from './GrandChildComponent.vue';
export default {
components: {
GrandChildComponent
},
provide: {
message: '这是通过Provide/Inject传递的消息'
}
};
</script>
- 子孙组件:
<template>
<div>{
{ message }}</div>
</template>
<script>
export default {
inject: ['message']
};
</script>
- Refs(访问子组件实例)
- 父组件可以通过
refs
来直接访问子组件的实例,从而调用子组件的方法或者访问子组件的数据。不过这种方式在一定程度上破坏了组件的封装性,应该谨慎使用。
- 示例:
- 父组件:
<template>
<div>
<child - component ref="child"></child - component>
<button @click="callChildMethod">调用子组件方法</button>
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
callChildMethod() {
this.$refs.child.childMethod();
}
}
};
</script>
- 子组件:
<template>
<div>子组件</div>
</template>
<script>
export default {
methods: {
childMethod() {
console.log('子组件方法被调用');
}
}
};
</script>