Vue自定義元件事件傳遞:EventBus部分

丨大麥發表於2018-06-24

前言

元件化應用構建是Vue的特點之一,因此我們在Vue的實際開發過程中會經常需要封裝自定義元件,以提高開發的效率。 而元件在大部分情況下並不會孤立的存在,它必然會與父元件和兄弟元件產生資料的互動。所以在這裡為大家總結兩種元件資料互動的方式:EventBus和利用Vuex框架進行狀態管理。

我會通過兩種不同的互動方式,它們對於父子元件間資料互動和兄弟元件間資料互動。

由於篇幅關係,本文主要介紹EventBus進行資料訊息傳遞;關於運用Vuex框架進行狀態管理在下一篇文章中介紹。

Vuex框架介紹:Vuex入門教程

案例介紹

本章節會有大量的程式碼示例,為了讓讀者閱讀輕鬆,做如下目錄和元件介紹。本章節主要運用了兩個子元件和一個父元件。

子元件檔名:SearchInput.vueSearchItem.vue

父元件檔名:StateView.vue

目錄結構展示:

Vue自定義元件事件傳遞:EventBus部分

1、SearchInput.vue

元件介紹:一個輸入框,它會onInput方法去監聽輸入內容,並呼叫方法,將輸入框內的資料傳遞出去。

程式碼展示:

<template>
  <div>
    <input placeholder="搜尋內容"  v-model="searchContent"/>
  </div>
</template>

<script type="text/ecmascript-6">
  export default{
    data(){
      return{
        searchContent:""
      }
    },
    props:{

    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>


複製程式碼

SearchItem.vue

元件介紹:一個span,它主要用來接收父元件傳遞的內容和接收同胞元件輸入框傳遞的內容,並進行展示。

程式碼示例:

<template>
    <span class="item">
      {{content}}
    </span>
</template>

<script type="text/ecmascript-6">
  export default{
    data(){
      return{
        content:this.itemContent
      }
    },
    props:{
      itemContent:{
        type:String,
        required:true
      }
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">
  .item
    background #f4f4f4
    padding 3px 5px
    box-sizing border-box
    display inline-block
    cursor pointer
</style>

複製程式碼

StateView.vue

元件介紹:父元件,主要展示頁面和載入子元件

程式碼示例:

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜尋2"/>
      <search-item itemContent="熱門搜尋3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'

export default{
  data () {
    return {
      content:"接收輸入框的值"
    }
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製程式碼

正文

EventBus

1、父元件傳送資料給子元件,可以通過子元件定義的props自定義屬性,去傳遞資料

2、EventBus其實就是通過例項化一個Vue例項,然後通過該例項的$emit方法傳送資料訊息和$on方法接收資料訊息。它適用在子元件傳送訊息給父元件或子元件傳送訊息給兄弟元件。

我們看下一個下面案例主要展示了

1、通過props父元件(StateView)去為子元件(SearchItem)傳遞資料;

2、子元件(SearchInput)通過EventBus和父元件(StateView)、兄弟元件(SearchItem)傳遞資料;

目錄結構展示

Vue自定義元件事件傳遞:EventBus部分

效果展示

Vue自定義元件事件傳遞:EventBus部分

程式碼展示:(粗體表示變化部分)

1、第一步:自定義一個EventBus(SearchEvent.js)

import Vue from 'vue'
export default new Vue()
複製程式碼

在這裡我們new了一個Vue的例項,並將它輸出。

第二步:子元件通過EventBus傳送資料訊息

<template>
  <div>
    <input placeholder="搜尋內容" @input="sendEvent" v-model="searchContent"/>   //增加了@input=“sendEvent”,去監聽onInput事件,並回撥sendEvent方法
  </div>
</template>

<script type="text/ecmascript-6">
  import searchEvent from '../event/SearchEvent'     //匯入EventBus
  export default{
    data(){
      return{
        searchContent:""
      }
    },
    methods:{
      sendEvent:function(){      //定義sendEvent方法,在input中監聽onInput,並回撥該方法
           /**
         * 通過匯入的searchEvent呼叫$emit方法去傳送資料訊息。
         * 第一個引數為事件名,到時候我們要通過該事件名去接收數
         * 第二個引數為資料值,如果只有一個引數,我們可以直接傳遞該引數
         * 如果有兩個及以上的引數,我們可以通過物件的形式去傳遞。
         */
        searchEvent.$emit("search",this.searchContent)
        //多個引數傳遞的示例:
        //searchEvent.$emit("search",{"content":this.searchContent,"valTwo":"valTow"})
      }
    },
    props:{

    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製程式碼

在上面的示例我們主要做了以下事情: 1、匯入EventBus

2、通過@input="sendEvent"去監聽onInput事件,並發現輸入框內內容有改變時,回撥sendEvent方法,呼叫EventBus.emit()方法把資料訊息傳送出去

第三步父元件(StateView)和子元件(SearchItem)接收資料訊息

StateView.vue

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>   //通過props去為子元件傳遞(動態資料:content)資料
      <search-item itemContent="熱門搜尋2"/>  //通過props去為子元件傳遞(固定資料:熱門搜尋2)資料
      <search-item itemContent="熱門搜尋3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'   //匯入EventBus
export default{
  data () {
    return {
      content:"接收輸入框的值"
    }
  },
  mounted(){
    /**
     * 在mounted接受資料訊息,$on接受兩個引數。
     * 第一個引數是訊息事件名,應該與傳送資料訊息的第一個引數相同,否則接收不到資料訊息
     * 第二個引數是一個函式,對資料訊息事件做處理;該函式帶一個引數,則是資料。
     */
    searchEvent.$on('search',(val)=>{
      this.content=val;
      //示例:如果資料傳遞的是物件形式
      // this.content=val.content;
    })
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製程式碼

在上面的示例我們主要做了以下事情:

1、在父元件,我們通過SearchItem的props去傳遞了資料。

2、通過在元件mounted生命週期中呼叫EventBus.on()方法去接收子元件(SearchInput)的資料訊息,並對content進行修改值

SearchItem.vue

<template>
    <span class="item">
      {{content}}
    </span>
</template>

<script type="text/ecmascript-6">
  import searchEvent from '../event/SearchEvent'  //匯入EventBus
  export default{
    data(){
      return{
        content:this.itemContent
      }
    },
    props:{
      itemContent:{
        type:String,
        required:true
      }
    },
    mounted(){
    /**
     * 在mounted接受資料訊息,$on接受兩個引數。
     * 第一個引數是訊息事件名,應該與傳送資料訊息的第一個引數相同,否則接收不到資料訊息
     * 第二個引數是一個函式,對資料訊息事件做處理;該函式帶一個引數,則是資料。
     */
      searchEvent.$on('search',(val)=>{
        this.content=val;
      })
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">
  .item
    background #f4f4f4
    padding 3px 5px
    box-sizing border-box
    display inline-block
    cursor pointer
</style>

複製程式碼

在上面的示例我們主要做了一事情:

通過在元件mounted生命週期中呼叫EventBus.on()方法去接收子元件(SearchInput)的資料訊息,並對content進行修改值。

我們可以感受到SearchInput一傳送資料訊息,所有註冊接收search事件的地方都會接收到資料訊息

覆盤:

1、父元件給子元件進行資料傳遞可以通過props進行傳遞。

2、子元件給父元件進行訊息傳遞或子元件給兄弟元件進行訊息傳遞可以通過EventBus去例項化一個Vue,並通過該例項的$emit$on方法去傳遞和接收資料訊息。

3、資料訊息一旦傳送,所有註冊了接收該資料訊息的地方都會接收到該資料訊息。

我的大麥,如果喜歡我的文章請給我一個小心心哦。

相關文章