vue組件之間的傳值——中央事件總線與跨組件之間的通訊($attrs、$listeners)

vue組件之間的通訊有不少種方式,最經常使用到的就是父子組件之間的傳值,可是當項目工程比較大的時候,就會出現兄弟組件之間的傳值,跨級組件之間的傳值。不能否認,這些均可以相似父子組件一級一級的轉換傳遞,可是當項目比較大,功能比較複雜的時候,就會變得比較冗餘,代碼不利於維護;這時候可能會有不少人使用到vuex,可是若是項目中多個組件共享狀態比較少,項目比較小,而且全局狀態比較少,好像就沒有使用vuex來管理數據的必要。vue

1、中央事件總線(eventBus)vuex

主要是經過在要相互通訊的兄弟組件之中,都註冊引入一個新的vue實例,而後經過分別調用這個實例的事件觸發和監聽來實現通訊和參數傳遞,也就是咱們常說的bus車事件。性能

一、首先,全局註冊一個新的vue實例,能夠放在咱們經常使用的vue項目文件中this

js/event-bus.jsspa

import Vue from 'vue'
export default new Vue()

二、若是不想全局引用能夠,在使用的vue文件裏使用,舉個例子:contentLeft.vue,contentRight.vue 須要將contentLeft.vue與contentRight.vue互相通訊code

contentLeft.vuecomponent

<template>
  <div>
    {{message}}
    <button @click="handleClick">test</button>
  </div>
</template>

<script>
import bus from '../../assets/js/event-bus'

export default {
  data () {
    return {
      message: 'this is content here'
    }
  },
  props: {
    con: {
      type: String
    }
  },
  components: {
    descripe
  },
  methods: {
    handleClick () {
      bus.$emit('getDate', 'brathers!')
    }
  }
}
</script>

contentRight.vue blog

<template>
  <div>
    {{message}}
    <p v-for="(item,index) in meslist" :key="index">{{item}}</p>
  </div>
</template>

<script>
import bus from '../../assets/js/event-bus'
export default {
  data () {
    return {
      message: '',
      meslist: []
    }
  },
  created () {
    bus.$on('getDate', (val) => {
      console.log(val)
      this.message = val
      // this.meslist.push(val)
    })
  },
  beforeDestroy () {
    // 組件銷燬前須要解綁事件。不然會出現重複觸發事件的問題!!!!!!!!!!!!!
    bus.$off('getDate')
  }
}
</script>

當點擊contentLeft的按鈕的時候,contentRight的message值就獲取到了總left中傳過來的'brothers'生命週期

優勢:經過bus事件方法能夠簡單快捷的進行組件之間的傳值,在項目不大的時候,減小了對vuex的依賴事件

缺點:一、bus事件對生命週期比較嚴謹,當你bus.$emit發送事件時,若是兄弟組件還不存在,當真正打開兄弟組件時,此時在created裏面bus.$on是監聽不到傳遞的值的

二、bus事件不會隨着組件的關閉而自行銷燬,因此當路由切換時,bus事件會不停的觸發,若是數據量比較多的時候,可能會比較影響性能吧,因此須要及時銷燬所綁定的bus事件

2、跨組件之間的通訊

vue2.4以後,跨組件之間的通訊能夠經過$attr和$listeners來實現

舉個例子,father.vue  child.vue  grandChild.vue

father.vue組件中傳值

<template>
  <div class="about">
    <p>子組件給父組件傳值,父組件再給父組件傳值</p>
    <child
      :con="con"
      :son="son"
      @getCData = "getCData"
    ></child>
  </div>
</template>

<script>
import child from './components/child'

export default {
  data () {
    return {
      test: 'test',
      con: 'child',
      son: 'child-child'
    }
  },
  components: {
    child
  },
  methods: {
    getGrandChildData (val) {
      this.son = val
      console.log('這是來自grandchild組件的數據:' + val)
      console.log(this.son)
    }
  }
}
</script>

child.vue組件中設置grandChild組件的$attr和$listner屬性

<template>
  <div>
    {{message}}
    <i class="get-data">{{con}}</i>
    <grandChild v-bind="$attrs" v-on="$listeners"></grandChild >
    <button @click="handleClick">test</button>
  </div>
</template>

<script>
import grandChild from './grandChild '

export default {
  data () {
    return {
      message: 'this is content here'
    }
  },
  props: {
    con: {
      type: String
    }
  },
  components: {
    grandChild 
  }
}
</script>

grandChild.vue組件能夠經過$attr監聽到爺爺級組件的值,再經過觸發事件向爺爺級組件傳遞修改值

<template>
  <div>
    {{list}}
    <p class="get-data">{{$attrs.son}}</p>
    <input type="text" v-model="$attrs.son">
    <button @click="passData($attrs.son)">按一下</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      list: 'ceshixia'
    }
  },
  methods: {
    passData (val) {
      // 觸發事件,改變值爺爺級組件的值
      this.$emit('getGrandChildData', val)
    }
  }
}
</script>

以上就能夠實現跨級組件之間的傳值,能夠引用到各類場景中去

相關文章
相關標籤/搜索