1. 组件通讯模式介绍
在Vue中,组件通讯是非常重要的一部分。在组件化开发的时代下,组件之间通讯的模式也随之发生了变化。Vue提供了多种通讯方式,如:
props / $emit
provide / inject
event bus
vuex
这些方式在不同的场景下有不同的使用场景。接下来将详细介绍这些通讯方式。
2. props / $emit
2.1 父组件向子组件传递数据
父组件向子组件传递数据,可以使用props。在父组件中,使用props来定义要传递的属性:
//父组件
<template>
<childComponent :message="msg"></childComponent>
</template>
<script>
import childComponent from './childComponent.vue'
export default {
name: 'parentComponent',
components: {
childComponent
},
data() {
return {
msg: 'Hello'
}
}
}
</script>
//子组件
<template>
<div>{{ message }}</div>
</template>
<script>
export default {
name: 'childComponent',
props: {
message: String
}
}
</script>
在父组件中,通过下面这一行代码向子组件传递了一个名为message的属性:
<childComponent :message="msg"></childComponent>
在子组件中,使用props来接收这个属性:
export default {
name: 'childComponent',
props: {
message: String
}
}
2.2 子组件向父组件传递数据
子组件向父组件传递数据,可以使用$emit。在子组件中,使用$emit来触发一个事件,并将需要传递给父组件的数据作为参数传递进去:
//子组件
<template>
<button @click="$emit('add')">add</button>
</template>
<script>
export default {
name: 'childComponent',
}
</script>
在父组件中,使用v-on来监听这个事件,并将$event(即子组件传递的数据)作为参数接收:
//父组件
<template>
<childComponent @add="add"></childComponent>
</template>
<script>
import childComponent from './childComponent.vue'
export default {
name: 'parentComponent',
components: {
childComponent
},
methods: {
add() {
//do something here
}
}
}
</script>
3. provide / inject
3.1 父组件通过provide向子组件提供数据
provide是Vue中新增的一个选项,它可以用来向子组件提供数据。在父组件中,使用provide来定义要提供的数据:
//父组件
<template>
<childComponent></childComponent>
</template>
<script>
import childComponent from './childComponent.vue'
export default {
name: 'parentComponent',
components: {
childComponent
},
provide() {
return {
name: 'Vue'
}
}
}
</script>
//子组件
<template>
<div>{{ name }}</div>
</template>
<script>
export default {
name: 'childComponent',
inject: ['name']
}
</script>
在父组件中,通过provide向子组件提供了一个名为name的数据。在子组件中,使用inject来接收这个数据:
export default {
name: 'childComponent',
inject: ['name']
}
3.2 子组件通过inject向父组件提供数据
子组件通过inject向父组件提供数据与props的用法类似。在子组件中,使用inject来定义要提供的数据:
//父组件
<template>
<childComponent></childComponent>
</template>
<script>
import childComponent from './childComponent.vue'
export default {
name: 'parentComponent',
components: {
childComponent
},
methods: {
add(value) {
//do something here
}
}
}
</script>
//子组件
<template>
<button @click="add('Vue')">add</button>
</template>
<script>
export default {
name: 'childComponent',
inject: ['add']
}
</script>
在子组件中,使用inject来接收父组件传递进来的add方法,并将需要传递的数据作为参数传递给它:
export default {
name: 'childComponent',
inject: ['add']
}
4. event bus
event bus是一种基于vue实例的事件传递方式。通过创建一个vue实例作为event bus,组件之间可以通过事件的方式进行通讯。
首先,我们需要在一个单独的js文件中创建一个vue实例来作为event bus:
//eventBus.js
import Vue from 'vue'
export default new Vue()
在需要通讯的组件中,引入该实例,并通过$on来监听事件,通过$emit来触发事件并传递数据:
//组件A
<template>
<div>{{ message }}</div>
</template>
<script>
import eventBus from './eventBus'
export default {
name: 'componentA',
data() {
return {
message: ''
}
},
mounted() {
eventBus.$on('message', message => {
this.message = message
})
}
}
</script>
//组件B
<template>
<button @click="send">send</button>
</template>
<script>
import eventBus from './eventBus'
export default {
name: 'componentB',
methods: {
send() {
eventBus.$emit('message', 'Hello')
}
}
}
</script>
5. vuex
vuex是Vue中的一个状态管理库,它允许在应用程序中集中管理各种组件之间的共享状态。在vuex中,所有的状态都被存储在一个单一的store中,组件之间通过store来进行数据的共享。
在使用vuex之前,首先需要安装vuex并创建一个store:
//store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
message: ''
},
mutations: {
setMessage(state, message) {
state.message = message
}
},
actions: {
setMessage(context, message) {
context.commit('setMessage', message)
}
}
})
在组件中,可以使用mapState、mapMutations、mapActions等辅助函数来简化vuex的操作。这里只介绍最基本的方式:
//组件A
<template>
<div>{{ message }}</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
name: 'componentA',
computed: {
...mapState({
message: state => state.message
})
}
}
</script>
//组件B
<template>
<button @click="send">send</button>
</template>
<script>
import { mapActions } from 'vuex'
export default {
name: 'componentB',
methods: {
...mapActions(['setMessage']),
send() {
this.setMessage('Hello')
}
}
}
</script>
在组件A中,使用mapState来实现对state的映射。在组件B中,使用mapActions来实现对actions的映射,并在send方法中通过this.setMessage来触发setMessage这个action,来改变state的值。
6. 总结
组件之间通讯是Vue中非常重要的一部分,Vue提供了多种通讯方式。在实际应用中,根据不同的场景选择合适的通讯方式,可以更加方便的实现组件之间的通讯。