最近碰到了比較多的關于vue的eventBus的問題,之前定技術選型的時候也被問到了,vuex和eventBus的使用範圍。是以簡單的寫一下。同時有一種特殊的實作方案。 有這麼幾種資料傳遞方式,vuex、props、eventBus和特殊的eventBus。

不介紹,資料量和複雜度達不到不用它你才會向下看。
props*demo*
父子元件傳值,官方api,隻寫個demo。
1.父元件<son :info="info" @update="updateHandler"/>
// data
info: 'sendToSon'
// methods
updateHandler (newVal) {
this.info = newVal
}
2.子元件 // props
props: ['info']
// 向上傳值,某個方法中使用
this.$emit('update', 'got')
父向子傳值-->props 子向父傳值-->子元件綁定事件回調定義在父元件,子元件觸發此事件。 因不推薦子元件内直接修改父元件傳入的props,需使用自定義事件。 限制 父子元件。 eventBus demo bus皆為導入的bus執行個體
// bus
const bus = new Vue()
// 資料接收元件
// 目前元件接收值則
bus.$on('event1', (val)=>{})
// 資料發出元件
// 目前元件發出值則
bus.$emit('event1', val)
//
可以看出本質是一個vue執行個體充當事件綁定的媒介。 在所有執行個體中使用其進行資料的通信。 雙(多)方使用同名事件進行溝通。
問題$emit
時,必須已經
$on
,否則将無法監聽到事件,也就是說對元件是有一定的同時存在的要求的。(注:路由切換時,新路由元件先 created,舊路由元件再destoryed,部分情況可以分别寫入這兩個生命周期,見此問題)。
$on
在元件銷毀後不會自動解除綁定,若同一元件多次生成則會多次綁定事件,則會一次
$emit
,多次響應,需額外處理。 資料非“長效”資料,無法儲存,隻在
$emit
後生效。 是以是否有一種更适用的方案呢? 特殊的eventBus?
demo我們先來看個代碼,線上代碼。 bus皆為導入的bus執行個體。
// bus
const bus = new Vue({
data () {
return {
// 定義資料
val1: ''
}//
},
created () {
// 綁定監聽
this.$on('updateData1', (val)=>{
this.val1 = val
})
}
})
// 資料發出元件
import bus from 'xx/bus'
// 觸發在bus中已經綁定好的事件
bus.$emit('update1', '123')
// 資料接收元件
{{val1}}
// 使用computed接收資料
computed () {
val1 () {
// 依賴并傳回bus中的val1
return bus.val1
}
}//
- 不同 正統的eventBus隻是用來綁定和觸發事件,并不關心資料,不與資料發生交集。而這個方案多一步将資料直接添加在bus執行個體上。且事件監聽與資料添加需提前定義好。 資料接收方不再使用
來得知資料變化,而是通過計算屬性的特征被動接收。 解決的問題 通信元件需同時存在?資料在bus上存儲,是以沒有要求。 多次綁定?綁定監聽都在bus上,不會重複綁定。 資料隻在$emit後可用?使用計算屬性直接讀取存在bus上的值,不需要再次觸發事件。$on
- 探讨 為什麼使用計算屬性 其實應該是為什麼不能直接添加到data上,如 data1: bus.data1?我們可以再看一段代碼,線上代碼。 将bus修改為
data () {
return {
// 多一層結構
val: {
result: 0
}//
}
},
created () {
this.$on('update1', val => {
console.log('觸發1', i1++)
this.val.result = val
})
}
資料接收元件改為
// template
data中擷取直接修改值:{{dataResult}}
data中擷取直接修改值的父層:{{dataVal}}
computed中依賴直接修改值:{{computedResult}}
// js//
data () {
return {
// 擷取直接修改值
dataResult: bus.val.result,
// 擷取直接修改值的父層
dataVal: bus.val
}
},
computed: {
computedResult () {
// 依賴直接修改值
return bus.val.result
}
}//
可以看到,data中擷取直接修改值值的資料是無法動态響應的。
為什麼要用事件其實不用
$emit
觸發,使用 bus.val = 1直接指派也是可以的,那麼為什麼不這麼做呢? 簡化版的vuex 其實這種eventBus就是簡化版的vuex。 vue文檔中有這樣一段話: 元件不允許直接修改屬于 store 執行個體的 state,而應執行 action 來分發 (
dispatch
) 事件通知 store 去改變,我們最終達成了 Flux 架構。這樣約定的好處是,我們能夠記錄所有 store 中發生的 state 改變。 store對應 bus執行個體,
state對應 data
,
action
對應 事件, dispatch對應
$emit
。 同時vuex中元件擷取資料的方式正是通過計算屬性,那麼其實vuex和Flux架構的了解和使用也沒有那麼難不是嗎。
結語感謝您的觀看,如有不足之處,歡迎批評指正。
解析Vue-router相關幹貨及工作原理www.jianshu.com
CSS 布局經典問題大全www.jianshu.com