Vue中的组件通讯模式分析

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提供了多种通讯方式。在实际应用中,根据不同的场景选择合适的通讯方式,可以更加方便的实现组件之间的通讯。