vue工程利用pubsub-js實現兄弟元件之間的通訊

pubdreamcc發表於2019-03-21

前言

專案是基於vue-cli建立的,不會搭建vue開發環境的同學可以百度,這裡不再贅述。

步驟流程

vue專案搭建完成之後的檔案圖如下:
vue工程利用pubsub-js實現兄弟元件之間的通訊

我的上一篇部落格已經詳細敘述vue工程中各個檔案的作用,不清楚的同學可以移步看這裡

  1. 專案中需要用到axios這個包,所以我們先安裝相應的包,專案終端輸入:npm install axios -S 。後面兄弟元件之間通訊我們採用的是“訂閱訊息/釋出訊息”的方法,這個也是一個包,所以也先安裝下依賴包 npm i pubsub-js -S。安裝完成後可以在專案package.json檔案中看到對應依賴包。
    vue工程利用pubsub-js實現兄弟元件之間的通訊

  2. src資料夾下components下建立main.vue和header.vue兩個元件,分別代表專案中主體區域和頭部區域,等下需要掛載到根元件App下。
    vue工程利用pubsub-js實現兄弟元件之間的通訊

  3. header.vue檔案中相關程式碼:
<template>
  <div id="header">
    <div class="container">
      <div class="row center">
        <h1>Search Github Users</h1>
        <input type="text" v-model="searchName">
        <input type="button" value="Search" class="btn btn-primary" placeholder="請輸入github使用者名稱" @click="search">
      </div>
    </div>
  </div>
</template>
<script>
import PubSub from 'pubsub-js'
export default {
  name: 'Header',
  data () {
    return {
      searchName: ''   
    }
  },
  methods: {
    search ()
    {
      // 釋出訊息
      const searchName = this.searchName.trim()
      if (searchName) {
        PubSub.publish('search', searchName)
      } 
    }
  }
}
</script>
<style>
#header{
  height: 200px;
}
.container .center{
  text-align: center;
}
</style>

main.vue檔案中相關程式碼:

<template>
  <div id="main">
    <h1 v-if="firstview">請輸入搜尋使用者的名稱</h1>
    <h1 v-if="loading">loading</h1>
    <h1 v-if="errormsg">{{errormsg}}</h1>
      <div class="row">
        <div class="col-xs-6 col-md-3" v-for="(user,index) in users" :key="index">
          <a :href="user.url">
            <img :src="user.avatar_url">
          </a>
          <span>{{user.name}}</span>
        </div>
      </div>
  </div>
</template>
<script>
import PubSub from 'pubsub-js'
import axios from 'axios'
// https://api.github.com/search/users?q=
export default {
  name: 'Main',
  data () {
    return {
      firstview: true,
      loading: false,
      errormsg: '',
      users: null // [{url:' ',name:'',avatar_url:""}]
    }
  },
  mounted () {
    // 訂閱訊息
    PubSub.subscribe('search', (msg, searchName) => {
      const url = 'https://api.github.com/search/users?q='+searchName
      // 更新狀態
      this.firstview = false
      this.loading = true
      this.users=null
      this.errormsg=''
      axios.get(url).then((response) => {
        const result = response.data
        const users = result.items.map(item => ({
          url: item.html_url,
          avatar_url: item.avatar_url,
          name: item.login 
        }))
        // 更新請求成功的狀態
        this.loading=false
        this.users=users
      }).catch(error => {
        this.loading=false
        this.errormsg='搜尋失敗'
      })
    })
  }
}
</script>
<style>
#main > .row ,#main h1{
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
#main > .row > div{
  float: left;
  width: 100px;
  padding: 0;
  text-align: center;
  color: red;
  font-size: 18px;
  margin: 0 10px;
}
.row a img{
  width: 100px;
  height: 100px;
}
</style>

這裡主要是詳細解釋下main.vue中相關程式碼。在專案的主體區域中,我們需要通過後臺返回的資料進行頁面的渲染。標籤模板中主要是通過v-for="(item,index) in items" :key="index"指令遍歷得到的陣列,進行頁面渲染,利用v-for我們可以輕鬆得到一組類似的結構,而不必多次寫一些重複的html標籤。在元件模板物件中我們定義了一組資料資訊,
vue工程利用pubsub-js實現兄弟元件之間的通訊
這裡的users主要是儲存由後臺返回回來的一組資料,可以供頁面進行渲染載入。另外三種皆為不同的狀態標誌屬性,當我們進行不同的操作,或者傳送Ajax請求(成功?失敗)都可以改變相應的狀態值從而使頁面呈現不同狀態。

  1. pub-sub庫的使用。
    專案中我們頭部header需要向後臺傳送關鍵字,後臺根據得到的關鍵字進行相應的操作,返回專案需要的資料。main主體區域中需要利用後臺返回的資料,進行頁面的渲染,main區域中必定會利用header中提供的關鍵字傳送ajax請求,所以這就牽扯到元件之間的通訊問題,pubsub-js就是用來實現元件之間通訊的。兄弟元件之間通訊如果利用props屬性,需要藉助父元件來實現,pubsub跨越元件之間的關係階層進行通訊。pubsub-js也就是我們所說的訂閱訊息和釋出訊息,訂閱訊息可以理解為事件的監聽,釋出訊息可以理解為觸發事件。我們在header中點選搜尋會通知main區域向後臺傳送Ajax請求,所以我們在header中釋出訊息,main中訂閱訊息。
    vue工程利用pubsub-js實現兄弟元件之間的通訊

利用pubsub,首先需要匯入這個包。search按鈕點選的時候,我們可以在按鈕點選的回撥函式裡去釋出訊息。釋出訊息是PubSub.publish()方法,這裡需要提供兩個引數,"釋出的訊息名","提供給訂閱者的引數",這裡的引數是輸入框的關鍵字。

main區域在元件的生命週期函式mounted(頁面載入完成)中訂閱訊息。訂閱訊息是PubSub.subscribe()方法,這裡接受兩個引數,"釋出的訊息名","事件的監聽函式",這裡事件的監聽函式需要兩個引數:一個是msg(釋出的訊息名,無用),一個是searchName(釋出者傳來的引數)。我們在事件的監聽裡面去傳送Ajax請求,更新頁面。
vue工程利用pubsub-js實現兄弟元件之間的通訊

  1. 專案完成後的效果圖:
    vue工程利用pubsub-js實現兄弟元件之間的通訊

字尾

如果你覺得這個對你有幫助,歡迎轉載,煩請註明出處。同時也歡迎大家在GitHub上和我一起進階前端。

找到我:GitHub

找到我:知乎

相關文章