首頁 >web前端 >js教程 >vue組件通訊的方法介紹(附程式碼)

vue組件通訊的方法介紹(附程式碼)

不言
不言轉載
2019-03-19 10:51:002293瀏覽

這篇文章帶給大家的內容是關於vue元件通訊的方法介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

vue 的元件化應該是其最核心的想法了,無論是一個大的頁面還是一個小的按鈕,都可以稱之為元件。基於 Vue 的開發,就是在寫一個個元件,無論是基礎元件還是業務元件,最後都是要拼裝在一起。依照組件的層級關係,可以把組件之間的關係歸納為:父子關係、隔代關係、兄弟關係,無關聯關係。

$ref 、$parent 、$children

基於目前情境的,可以透過 $ref 、$parent 、$children 存取元件實例,可以直接呼叫元件的方法或存取資料。其中 $parent 可以存取目前元件的父元件,$children 可以存取目前元件的所有子元件。雖然 $parent 和 $children 都可以取得元件實例,但是它們無法在跨級或兄弟間通信,這是它們的缺點。

provide 、inject

provide / inject 是 Vue 在 2.2.0 版本後新增的 API。

這對選項需要一起使用,以允許一個祖先組件向其所有子孫後代注入一個依賴,不論組件層次有多深,並在起上下游關係成立的時間裡始終生效。

也就是在父元件中提供一個值,並且在需要使用的子孫元件中註入改值,即:

// Parent.vue
export default {
    provide() {
        return {
            name: 'Stone'
        }
    }
}
// Child.vue
export default {
   inject: ['name'],
   mounted() {
       console.log(this.name)
   }
}

不只是 Child.vue ,只要是 Parent.vue 的子組件,無論隔多少代,都可以透過這個的方式註入。這種多層次元件透傳的方式可以保證單向資料流的清晰性,例如像使用者資訊這樣的全域訊息,就可以藉助這兩個 API 來完成,而沒有引入第三方函式庫 vuex。

取代Vuex

vuex 是把資料集中管理,然後哪裡需要就在哪裡獲取,按照這個思路,我們可以在根組件 App.vue 中註入全局信息,並且在頁面的任何地方使用。

// App.vue
<template>
  <div>
    <router-view></router-view>
  </div>
</template>
export default {
    provide() {
        return {
            userInfo: this.user
        }
    },
    data() {
        return {
            user: {}
        }
    },
    methods: {
      getUserInfo () {
        $.ajax('/user/info', (data) => {
          this.user = data
        })
      }
    }
}

把整個 App.vue 的實例 this 對外提供, 這樣其他頁面就可以透過 this.userInfo 來取得使用者資訊。

<template>
  <div>
    {{ userInfo }}
  </div>
</template>
<script>
  export default {
    inject: ['userInfo']
  }
</script>

$dispatch 、 $broadcast

這兩個API 是Vue 1.0 版本的,$dispatch 用於向上級派發事件,$broadcast 用於向下級廣播事件的,它們在2.0版本中已經被廢棄了。

因為基於元件樹結構的事件流方式有時讓人難以理解,並且在元件結構擴展的過程中會變得越來越脆弱。

不過我們可以自行實作 dispatch 和 broadcast 方法,用於元件的跨層級通訊。它們實現的關鍵在於如何正確找到所要溝通的元件,也就是透過配對元件的 name 選項向下或向上尋找元件。

這兩個方法都需要傳遞3 個參數,第一個參數是要通訊元件的name 選項值,第二個是自訂事件名稱,第三個是要給通訊元件傳遞的值。在 dispatch 裡,透過 while 迴圈不斷向上尋找父元件,直到查找到 componentName 與某個父級元件的 name 選項相符時結束,此時改父元件就是要通訊的元件。 broadcast 方法與 dispatch 類似,是透過 forEach 迴圈向下尋找子元件。最後封裝一個 mixins 來方便重複使用。

// emitter.js 
function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    const name = child.$options.name;
    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat([params]));
    }
  });
}
export default {
  methods: {
    dispatch(componentName, eventName, params) {
      let parent = this.$parent || this.$root;
      let name = parent.$options.name;
      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;
        if (parent) {
          name = parent.$options.name;
        }
      }
      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

透過 mixins 混入元件,實現元件間的通訊。

<!-- Parent.vue -->
<template>
  <button @click="handleClick">
    触发事件
    <Child></Child>
  </button>
</template>
<script>
import Emitter from "../assets/js/emitter.js";
import Child from "./Child.vue";
export default {
  name: "Parent",
  mixins: [Emitter],
  created() {
    this.$on("on-message", message => {
      console.log(message);
    });
  },
  components: {
    Child
  },
  methods: {
    handleClick() {
      this.broadcast("Child", "on-message", "Hello, I am Parent Component");
    }
  }
};
</script>
<!-- Child.vue -->
<template>
  <div></div>
</template>
<script>
import Emitter from "../assets/js/emitter.js";
export default {
  name: "Child",
  mixins: [Emitter],
  mounted() {
    this.$on("on-message", message => {
      console.log(message);
      this.dispatch("Parent", "on-message", "Copy that, I am Child Component");
    });
  }
};
</script>

比起Vue 1.0 版本內建的兩個API,自行實作的方法有以下不同:

  • 需要額外傳入元件的name 作為第一個參數;
  • 配對到元件就會停止循環,不會冒泡;
  • 傳遞的值只能是一個參數,如果需要傳遞多個參數,只能透過物件或陣列的形式;

其他方法

在vue 中元件的通訊還有其他的手法,例如:

  1. props$ emit
<!-- Parent.vue -->
<template>
  <Child :info="info"
         @update="onUpdateName"></Child>
</template>
<script>
import Child from "./Child.vue";
export default {
  data() {
    return {
      info: {
        name: "stone"
      }
    };
  },
  components: {
    Child
  },
  methods: {
    onUpdateName(name) {
      this.info.name = name;
    }
  }
};
</script>
<!-- Child.vue -->
<template>
  <div>
    <div>{{info.name}}</div>
    <button @click="handleUpdate">update</button>
  </div>
</template>
<script>
export default {
  props: {
    info: {
      type: Object,
      default: {}
    }
  },
  methods: {
    handleUpdate() {
      this.$emit("update", "new-name");
    }
  }
};
</script>

父元件將自己的方法傳遞給子元件,子元件呼叫方法傳送資料給父元件使用event bus事件匯流排$attrs 、$listenersVue 2.4 新增的API。

$attrs 包含了父作用域中不作為 prop 被識別 (且獲取) 的特性綁定 (class 和 style 除外)。

$listeners 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。 Vuex 集中式狀態管理

寫在最後

不同的通信方法適用於不同的場景,既可以透過Vue 內建的API 來通信,也可以透過自訂事件的方式實現通信方法,當應用程式夠複雜情況下,就可以使用Vuex 進行資料管理。

這篇文章到這裡就已經全部結束了,更多其他精彩內容可以關注PHP中文網的JavaScript教學影片專欄!

以上是vue組件通訊的方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除