vue中组件通信的几种方式

       我们知道,vue中的一个大页面是由多个子组件组成,组件之间的关系往往错综复杂,因此我们了解组件的通信方式成为vue中的重中之重。这篇文章就来总结一下vue项目中的几种通信方式。

一. 父子组件通信

1.props/$emit

 父组件通过props向子组件传递数据,子组件通过$emit触发父组件的方法,从而实现子到父的通信

<!--父组件-->
<template>
  <div class="parent">
    <!-- 通过v-bind或 ":" 父组件向子组件传递value-->
    <!-- 子组件中通过$emit触发, 父组件中通过v-on 或 "@"  接受emit的方法,进而实现子向父数据传递 -->
    <child :myValue="value" @changeValue="changeValue"></child>
  </div>
</template>

<script>
import Child  from './Child'
export default {
  name: 'Parent',
  components: { Child  },
  data() {
    return {
      value: '我要传给子组件'
    }
  },
  methods:{
      changeValue(changedValue){
        this.value = changedValue
      }
  }
}
</script>



// 子组件Child.vue
<template>
  <div class="child" @click="emitParent">
    {{myValue}}
  </div>
</template>

<script>
import Child  from './Child'
export default {
  name: 'Child',
  props: {  // 子组件通过props接受
    myValue: String,
  },
  data() {
    return {
      
    }
  },
  methods:{
    emitParent(){
        // 子组件中通过$emit触发, 父组件中通过v-on 或 "@"  接受emit的方法,进而实现子向父数据传递
        this.$emit('changeValue', this.myValue + 1)
    }
  }
}
</script>

 2.$parent/$children(不推荐使用)

通过this.$parent可以拿到当前组件的父组件(如果有的话),通过this.$children可以拿到它的所有子组件(如果有的话),因为this.$children是一个数组,如果要拿到它特定的子组件,需要知道对应子组件所在的位置的下标。

 没有特殊情况一般不必使用,这里仅作了解。

二. 非父子组件通信

 1.provide/inject

provide/inject是vue 2.2.0 新出的api,主要用于父、子、孙及所有后代之间的通信。通过provide属性在父组件中提供指定属性,在需要的子孙组件(不论组件嵌套有多深)中通过inject注入所需属性。

 举个例子

// Father.vue
<template>
  <div>
	<child></child>
  </div>
</template>

<script>
import Child from '../components/Child.vue'
export default {
  name: 'Father',
  provide: {
    for: 'demo'
  },
  components: {
    Child
  }
}
</script>
// Child.vue
<template>
  <div>
    {{for}}
  </div>
</template>

<script>
export default {
  name: 'Child',
  inject: ['for'],
}
</script>

2.ref/refs

ref: 如果在普通DOM元素上使用,则指向dom元素本身。如果用在组件元素上,则指向这个组件的实例。可以通过this.$refs.ref属性名使用组件的data、methods等。

 使用场景:一般可用于一些弹窗的显示和隐藏。

// 子组件 A.vue
<script>
export default {
  data () {
    return {
      name: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      console.log('hello')
    }
  }
}
</script>
// 父组件 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>

3.eventBus

eventBus俗称叫事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。

主要分为以下四步

  • 初始化eventBus,简单来说就是执行new Vue()
  • 在所需要的组件中导入eventBus,通过eventBus.$emit() 触发事件。
  • 在需要接受事件的组件中通过eventBus.$on()接受事件
  • eventBus.$off()来注销事件
// 创建event-bus
// event-bus.js

import Vue from 'vue'
export const EventBus = new Vue()
// 在所需组件中$emit()触发事件
// addtionNum.vue 中触发事件

<template>
  <div>
    <button @click="additionHandle">+加法器</button>    
  </div>
</template>

<script>
import {EventBus} from './event-bus.js'
console.log(EventBus)
export default {
  data(){
    return{
      num:1
    }
  },

  methods:{
    additionHandle(){
      EventBus.$emit('addition', {
        num:this.num++
      })
    }
  }
}
</script>
// 通过$on接收事件
// showNum.vue 中接收事件

<template>
  <div>计算和: {{count}}</div>
</template>

<script>
import { EventBus } from './event-bus.js'
export default {
  data() {
    return {
      count: 0
    }
  },

  mounted() {
    EventBus.$on('addition', param => {
      this.count = this.count + param.num;
    })
  }
}
</script>
// 通过$off移除事件
import { eventBus } from 'event-bus.js'
EventBus.$off('addition', {})

eventBus一般用于逻辑比较简单的系统,逻辑过于复杂,eventBus的维护会十分困难。这时候一般推荐使用vuex代替eventBus.

4.vuex

vuex是一种状态管理模式,它保存着组件的公用的状态,并且以相应的规则保证状态变化。vuex的核心就是一个store,它相当于是一个容器,里面包含有state,action,mutation,getter,modules等核心

  • state:用于数据的存储,是store中的唯一数据源
  • getters:如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关性计算
  • mutations:类似函数,改变state数据的唯一途径,且不能用于处理异步事件
  • actions:类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步操作
  • modules:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护

以下是一个简单的vuex实例

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

//可以通过以下方式来读取state
console.log(store.state.count)

store.commit("commit")

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值