组件之间的通信主要分为父子组件之间的通信和非父子组件之间的通信。本文介绍以下几种常见的组件之间的通信。
- props/$emit
- Vuex
- eventBus:事件总线
- ref
- provide/reject
- localStorage/sessionStorage
1、props/$emit:
主要用于父子组件之间的通信。父组件通过props的方式传值给子组件,子组件通过$emit调用父组件的方法
//父组件传字符串data给子组件,子组件在props里接收;子组件通过$emit调用父组件的test方法,需在子组件上注册test方法
//父组件:parent.vue
<template>
<children data="data" @onTest="test" />
</template>
<script>
import children from './children';
export default {
components:{children},
methods:{
test(data){
console.log(data)
}
}
}
</script>
//子组件:children.vue
<template>
<div>
children:: {{data}}
<button @click="test">调用父组件的test方法</button>
</div>
</template>
<script>
export default {
props:{
data:{
default:''
}
},
methods:{
test(){
this.$emit('onTest',{key:'传给父组件的数据'})
}
}
}
</script>
2、Vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用中所有组件的状态。每个单页面之间有独立的Vuex
Vuex中的核心概念:
1、state:设置vuex中的数据
2、getter:类似于vue中的计算属性,当一个state中的数据是依据另一个数据时,可以写在getter里。
3、mutations:改变state数据的唯一途径,不能用于异步处理事件
4、actions:类似于actions,用于提交mutation来改变状态,可包含任意异步操作
5、modules:当项目过大时,可以考虑每个模块有自己的state数据
以上概念可以根据自己的需求自行配置
//state/index.js:设置vuex的数据
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
});
//在vue文件中访问vuex数据,其他组件修改count数据时,该组件会自动更新数据
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['count'])
}
}
</script>
3、eventBus:事件总线
在vue中可以使用它来作为沟通桥梁。所有组件共用相同的事件中心,可以向该中心注册发送事件或接受事件。所以组件可以通知其他组件。要使用eventBus,首先要先创建一个事件总线并将其导出
//eventBus.js
import Vue from 'vue';
export const EventBus = new Vue();
//a.vue中通过$emit注册事件
<template>
<div>
<button @click="additionHandle">+加法器</button>
</div>
</template>
<script>
import {EventBus} from './eventBus.js'
export default {
data(){
return{
num:1
}
},
methods:{
additionHandle(){
EventBus.$emit('addition', {
num:this.num++
})
}
}
}
</script>
//在b.vue中通过$on接收事件
<template>
<div>计算和: {{count}}</div>
</template>
<script>
import { EventBus } from './eventBus.js'
export default {
data() {
return {
count: 0
}
},
mounted() {
EventBus.$on('addition', param => {
this.count = this.count + param.num;
})
}
}
</script>
//如果想移除事件监听者,可以如下操作
import { EventBus } from './eventBus.js'
EventBus.$off('addition', {})
4、ref
如果在普通dom元素上,引用指向的就是DOM元素,如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据。
// 父组件 app.vue
<template>
<component-a ref="comA"></component-a>
</template>
<script>
export default {
mounted () {
const comA = this.$refs.comA;
console.log(comA.name); // Vue.js
comA.sayHello(); // hello
}
}
</script>
//子组件
export default {
data () {
return {
name:'name'
}
},
methods: {
sayHello () {
console.log('hello')
}
}
}
5、provide/reject
在祖先级组件中,通过provide来提供变量,在子孙级组件中通过reject来注入变量。
//在祖先级组件中,注册for变量
<template>
<div>
<comB></comB>
</div>
</template>
<script>
import comB from './comB'
export default {
provide: {
for: "demo"
},
components:{
comB
}
}
</script>
//在子孙级组件中,注入for变量
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>
6、localStorage/sessionStorage
同一个域名下的页面共享localstorage和sessionStorage,所以各个组件也共享这些数据,但不能监测数据的实时变化。刷新页面时,vuex的值会被重置,结合localstorage/sessionStorage+vuex,可以实现数据的持久保存