首頁 > web前端 > js教程 > 主體

有關Vue2.0父子元件間實作派發機制(詳細教學)

亚连
發布: 2018-06-12 18:26:38
原創
1602 人瀏覽過

這篇文章主要介紹了淺談Vue2.0父子元件間事件派發機制,現在分享給大家,也給大家做個參考。

從vue1.x過來的都知道,在vue2.0中,父子元件間事件通訊的$dispatch和$broadcase被移除了。官方考慮是基於組件樹結構的事件流方式實在是讓人難以理解,並且在組件結構擴展的過程中會變得越來越脆落。特別是在組件層級比較深的情況下。透過廣播和事件分發的機制,就顯得比較混亂了。

官方在廢除的同時,也為我們提供了替換方案,包括實例化一個空的vue實例,使用$emit反應子組件上的狀態變化

1.使用$emit觸發事件

helloWorld.vue作為父元件,dialogConfigVisible變數控制子元件彈框顯示或隱藏。

configBox.vue作為子元件,假設為封裝的公告彈出視窗。

在父元件中helloWorld.vue 中

< template/>

  <config-box
   :visible="dialogConfigVisible"        
   @listenToConfig="changeConfigVisible"
 > </config-box>
登入後複製

script

 data(){
  return {
   dialogConfigVisible:true
  }
 }
  methods: {
   changeConfigVisible(flag) {
     this.dialogConfigVisible = flag;
   }
  }
登入後複製

然後,在子元件configBox.vue 中,主要在任意事件回呼中,使用$emit來觸發自訂的listenToConfig事件,後面還可以加上參數傳給父元件。例如,在子元件彈跳窗上點擊×關閉時,通知父元件 helloWorld.vue我要關閉了,主要方便父元件改變對應狀態變量,並傳入false到自訂的事件。

script

methods:{
 dialogClose() {
  this.show = false;
  this.$emit("listenToConfig", false)
 }
}
登入後複製

在子元件中,主動觸發listenToConfig事件,並傳入參數 false, 告訴父親元件 helloWorld.vue對話方塊要關閉了。這裡可以避免父元件中的狀態未變化,再次刷新頁面的時候對話方塊會自動出現。

2.實例化一個空的vue實例bus

這裡實例化一個bus 空vue實例,主要為了統一管理子元件和父元件相互通信,透過bus 作為媒介,先新建一個bus.js 文件,在裡面新建一個對象,父組件為table.vue, 子組件為tableColumn.vue

 // bus.js
 import Vue from "vue";
 export var bus = new Vue({
   data:{
    scrollY:false
   },
   methods:{
    updateScrollY(flag){
     this.scrollY = flag;
    }
   }
  })
登入後複製

然後分別引入:

 // table.vue
 <script>
 import {bus} from "./bus"
  export default {
   created(){
    bus.$on(&#39;getData&#39;,(argsData)=>{
     // 这里获取子组件传来的参数
     console.log(argsData);
     })

   }
  }

 </script>
登入後複製
 // tableColumn.vue
 <script>
  import {bus} from "./bus"
  export default{
   methods(){
    handleClick(){
     bus.$emit(&#39;getData&#39;,{data:"from tableColumn!"})
    }
   }
  }
 </script>
登入後複製

上面的父子元件中,父元件中利用bus註冊監聽事件getData,子元件中一旦有狀態變化,就觸發bus上對應的事件。

這種利用空實例的方式,相當於創建了一個事件中心,所以這種通信同樣適用於非父子組件間的通信,

3.多級父子元件通訊

有時,可能想要實作通訊的兩個元件不是直接的父子元件,而是祖父和孫子,或是跨越了更多層級的父子元件

#不可能由子組件一級一級的向上傳遞參數,來達到通訊的目的,雖然現在我們所理解的通訊都是這樣經過中轉的。可以透過while等循環,不斷向上遍歷,直到找到目標父元件,就在對應的元件上觸發事件。

下面就只element-ui實作的一個父子元件通訊的mixins,對於元件同步有很大的作用。在element-ui 的優點概述中也刻意提到這個元件通訊

function broadcast(componentName, eventName, params) {

 // 向下遍历每个子节点,触发相应的向下广播的 事件
 this.$children.forEach(child => {
  var name = child.$options.componentName;

  if (name === componentName) {
   child.$emit.apply(child, [eventName].concat(params));
  } else {
   broadcast.apply(child, [componentName, eventName].concat([params]));
  }
 });
}
export default {
 methods: {
   // 向上遍历父节点,来获取指定父节点,通过$emit 在相应的 组件中触发 eventName 事件
  dispatch(componentName, eventName, params) {
   var parent = this.$parent || this.$root;
   var name = parent.$options.componentName;
   // 上面的componentName 需要在每个vue 实例中额外配置自定义属性 componentName,
   //可以简单替换成var name = parent.$options._componentTag;

   while (parent && (!name || name !== componentName)) {
    parent = parent.$parent;

    if (parent) {
     name = parent.$options.componentName;
    }
   }
   if (parent) {
    parent.$emit.apply(parent, [eventName].concat(params));
   }
  },
  broadcast(componentName, eventName, params) {
   broadcast.call(this, componentName, eventName, params);
  }
 }
};
登入後複製

先定義兩個嵌套的元件f1.vue 和c1.vue,實例是:

 <f1>
  <c1></c1>
 </f1>
登入後複製

然後,分別定義兩個父子元件:

c2.vue

 <template>
   <section>
   <button type="button" name="button" @click="dispatchTest">点击一下,就可以</button>
  </section>
 </template>
<script type="text/javascript">
import Emitter from "../mixins/emitter";
export default {
name: "c2",
mixins: [Emitter],
componentName:&#39;c2&#39;,
methods: {
 dispatchTest() {
  this.dispatch(&#39;f1&#39;, &#39;listenerToC1&#39;, false);
 }
}
}
</script>
登入後複製

 f1.vue

<template type="html">
 <p class="outBox-class">
  <slot>
  </slot>
 </p>
</template>

<script type="text/javascript">
import Emitter from "../mixins/emitter";
export default {
name: "f1",
mixins: [Emitter],
componentName: &#39;f1&#39;,
mounted() {
 this.$on("listenerToC1", (value) => {
   alert(value);
 })
}
}
</script>
登入後複製

這樣,就可以在子元件中點選按鈕,觸發listenerToC1事件,在父元件中監聽到這個事件,

其實更$emit觸發事件類似。不同之處在於,這裡可以多層嵌套,不一定是直接的父子組件都可以觸發到。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

如何透過js將目前時間格式化?

使用vue引入css,less相關問題

#透過vue如何引入公共css檔案

在Vue中有關使用ajax方法有哪些?

以上是有關Vue2.0父子元件間實作派發機制(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板