Vue中的組件通訊

前言

vue中的組件通訊是必不可少的使用場景,回顧了平時使用vue中碰到的一些業務場景和對應採用的組件通訊方式,簡單地作了一個歸類總結,大體有如下一些通訊方式:vue

props/$emit

定義

最經常使用的父子組件通訊方式,父組件經過props向子組件傳值,子組件經過$emit事件向父組件觸發事件並傳值vuex

實例說明
//父組件
<parent :name="xxx" @updateFromChild="xxx"></parent>

//子組件
props: {
    name: {
        type: String,
        default: ''
    }
}
methods: {
    xxx () {
        this.$emit('updateFromChild', xx)
    }
}

$attrs 和 \$listeners

$attrs:

定義

子組件中獲取除了在props中定義以外的父組件中傳遞的屬性值(class 和 style 除外)數組

實例說明
//父組件
<parent name="小明" age=5 sex="男" home="杭州" class="parent"></parent>

//子組件
<script>
props: {
    name: {
        type: String,
        default: ''
    }
}
mounted () {
    console.log(this.$attrs)
    // {age:5, sex:"男", home:"杭州"}
}
</script>
使用場景

當孫組件中須要用到爺組件中的大量屬性,可是父組件卻不須要用到不少,只是做爲一箇中轉的傳遞,巧用$attrs能夠節省在父組件中寫的props值。dom

//父組件
<parent name="小明" age=5 sex="男" home="杭州" class="parent"></parent>

//子組件
<template>
  <grand-son :passAttr="$attrs"></grand-son>
</template>

props: {
    name: {
        type: String,
        default: ''
    }
}

$listener:

定義

包含了父做用域中的 (不含 .native 修飾器的) v-on 事件監聽器。ide

實例說明
//父組件
<parent @change="onChange" @hide="OnHide"></parent>

//子組件
<script>
mounted () {
    console.log(this.$listener)
    // {change:f, hide:f}
}
</script>
使用場景

子組件中調用父組件的方法函數


provide 和 inject

provide:

是一個對象或返回一個對象的函數。該對象包含可注入其子孫的屬性ui

inject:

是一個數組或者對象,包含祖先組件中注入的屬性this

實例說明:

//父組件:
<script>
provide: {
    name: '小明',
    sayName () {
        console.log('我是' + this.name)
    }
}
mounted() {
    this.name = '小花'
}
</script>


//子組件
<script>
inject:['name', 'sayName'],
mounted () {
    console.log(this.name); //小明
    this.sayName() //我是小明
}
</script>

能夠看到在子組件中的 mounted 中打印出了 inject 中傳遞進來的 name 屬性,併成功執行了 sayName 方法。並且 name 屬性值仍是'小明',並無變成'小花',並非響應式的。code

注意點

  • provide 和 inject 成對出現使用
  • provide 注入的屬性,在組件下的全部子孫組件中都能在 inject 中拿到
  • provide 和 inject 綁定並非可響應的,這是和props的本質區別

$parent 和 \$children

定義:

已建立的實例的父實例和子實例中,子實例能夠用 this.\$parent 訪問父實例,子實例被推入父實例的 \$children 數組中,父實例能夠用 this.$children 訪問子實例。對象

實例說明

//父組件
mounted(){
console.log(this.$children)
//能夠操做子組件的data,或者調用其methods中的方法
}

//子組件
mounted(){
console.log(this.$parent) //能夠拿到父組件中的屬性和方法
}

注意點

  • \$children和$parent不是響應式的
  • Vue官方有說明節制地使用 \$parent 和 $children - 它們的主要目的是做爲訪問組件的應急方法。

$refs

定義

一個對象,持有註冊過 ref attribute 的全部 DOM 元素和組件實例。經過this.$refs.xxx 能夠拿到 xxx 子組件中的data和methods。

實例說明
//父組件
<child ref="child"></child>

mounted(){
this.$refs.child.sayHello() // hello
}

//子組件
methods: {
    sayHello () {
        console.log('hello')
    }
}
注意點
  • this.$refs.xxx 必須在 xxx 組件渲染完成以後才能拿到,並非全部生命週期中都能取到。
  • 經過 this.$refs.xxx 進行對子組件的屬性操做並非響應式的,所以避免在computed中進行使用。這是一個很好的應急手段,經常使用於如下兩種使用場景

    1. 父組件直接調用子組件中的方法,節省沒必要要的代碼重寫
    2. 用來取代JQuery或者JS原生方法對dom元素的獲取

vuex

很少說,強大的複雜單頁面全局數據通訊管理中心,供頁面中的每一個組件進行全局數據的操做,並響應式到各個組件中。若是不知道自行搜索。這裏就簡單說兩個注意點

  • 注意vuex的使用場景,不要濫用,複雜的頁面數據管理,若是隻是簡單的數據通訊用props和$emit便可,不要爲了用而用,適合的纔是最好的
  • vuex中能夠根據狀況進行分模塊管理,代碼的可維護性會獲得進一步提高

eventBus

定義

對於非父子組件來講,能夠採用一箇中間介質來做爲一箇中央事件總線,完成事件的觸發和監聽,並進行傳值。

實例說明

第一步:建立事件總線:創建一個eventBus.js文件

//僅僅是爲了建立一個vue實例
import Vue from 'vue'
export default new Vue()

第二步:在傳值的源頭組件中引進事件總線,進行事件的觸發和傳值

<template>
 <div class = "source">
   <button @click="emitEvent">
 </div>
</template>

<script>
import eventBus from './eventBus.js'
export default {
  methods: {
      emitEvent: funciton () {
        eventBus.$emit('sendVal',param)
      }
  }
}
</script>

第三步:在傳值的目標組件中引進事件總線,進行事件的監聽和傳值的接收

<template>
 
</template>

<script>
import eventBus from './eventBus.js'
export default {
  data: function () {
      return {
          requireVal: ''
      }
  }
  mounted: function () {
    var that = this
    eventBus.$on('sendVal',function(val){
        that.requireVal = val
    }) 
  }
}
</script>

總結以下:

1.建立一個事件總線,例如demo中的eventBus,用它做爲通訊橋樑

2.在須要傳值的組件中用bus.$emit觸發一個自定義事件,並傳遞參數

3.在須要接收數據的組件中用bus.$on監聽自定義事件,並在回調函數中處理傳遞過來的參數

注意點
  • eventBus 特別適合非跨多個層級組件之間的通訊,解決了經過層層props傳遞的繁瑣,也避免了使用vuex的相對臃腫。
  • 缺陷在於若是不加說明和規範管理,容易找不到事件的觸發者和監聽者。所以建議放在單獨的js文件中建立好eventBus的vue實例,並在該文件中註釋好事件的觸發組件和監聽組件。
相關文章
相關標籤/搜索