文章目的 在我們開發 Vue 的專案時,每個元件檔案間都會有內外層的差別,例:一個 Root 下有兩個 side 每個 side 底下又有3個元件,當我們需要利用內層的資料來觸發外層的事件時,會需要一層一層的將資料向上傳遞,這會顯得較為麻煩,因此我們可以利用 event bus 的方式,直接將我們內層的資料傳遞給外層作使用。
event bus 簡介 event bus 的重點在於它可以幫我們把特定事件直接掛載到 Vue 的 原型下(Prototype),元件間透過 **$on(監聽)**以及 **$emit(觸發)**兩種行為來達到內層觸發外層事件的效果。
透過 event bus 將內層資料傳遞至外層觸發 alert 效果 新增 alert 模板 我們可以在 Vue Cli 的 components 資料夾底下新增一個 AlertMessage 的元件,並在裡面設計我們的 alert 模板。
將 event bus 掛載到原型上 掛載到原型上的目的是為了讓所有元件皆能使用。 在 Vue Cli 的 src 資料夾底下新增一個 bus.js 並在裡面輸入以下程式碼以完成掛載:
1 2 3 import Vue from 'vue' Vue.prototype.$bus = new Vue()
接著我們在進入點(main.js)下 import 這隻檔案進來。
在 AlertMessage 元件下做監聽 因為我們要讓底層元件觸發 event bus 時, event bus 會將相關資料傳遞到 AlertMessage 做使用,所以我們在 AlertMessage 中加入 event bus 的監聽,程式碼如下:
1 2 3 4 5 6 7 8 9 created () { const vm = this vm.$bus.$on('message:push' , (message, status = 'warning' ) => { vm.updateMessage(message, status) }) }
主要監聽時會有幾個屬性與參數可以做設定,自定義的名稱以及監聽的參數,基本上參數就會是內層傳遞上來的資料 ,接著可以將這些資料參數套用到元件內的其他 methods 中。 像在本次範例中將參數傳遞給 updateMessage
做使用,以下附上完整程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 export default { name: 'Navbar' , data () { return { messages: [] } }, methods: { updateMessage (message, status) { const timestamp = Math .floor(new Date () / 1000 ) this .messages.push({ message, status, timestamp }) this .removeMessageWithTiming(timestamp) }, removeMessage (num) { this .messages.splice(num, 1 ) }, removeMessageWithTiming (timestamp) { const vm = this setTimeout (() => { vm.messages.forEach((item, i ) => { if (item.timestamp === timestamp) { vm.messages.splice(i, 1 ) } }) }, 5000 ) } }, created () { const vm = this vm.$bus.$on('message:push' , (message, status = 'warning' ) => { vm.updateMessage(message, status) }) } }
完成 alert 部分的設定後我們可以將此元件 import 進要顯示訊息的 Dashboard 元件下。
1 2 3 4 5 6 import Alert from './AlertMessage' export default { components: { Alert } }
要記得將元件加入 HTML 裡。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <template > <div > <Navbar /> <Alert > </Alert > <div class ="container-fluid" > <div class ="row" > <Sidebar > </Sidebar > <main role ="main" class ="col-md-9 ml-sm-auto col-lg-10 px-4" > <router-view > </router-view > </main > </div > </div > </div > </template >
在內層的 Products 元件上新增 event bus 的觸發事件 透過 ajax 的失敗,觸發 event bus 將相關參數傳遞給 AlertMessage,以下是程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 this .$http.post(url, formData, { headers: { 'Content-Type' : 'multipart/form-data' } }).then((response ) => { console .log(response.data) if (response.data.success) { vm.status.fileUploading = false vm.$set(vm.tempProduct, 'imageUrl' , response.data.imageUrl) } else { this .$bus.$emit('message:push' , response.data.message, 'danger' ) } }) }
我們在之前 formData 上傳圖片的事件中,新增若上傳失敗就觸發 message:push
並根據我們當初自訂的格式回傳相關參數。 當 AlertMessage 收到我們回傳的參數時,就會根據這些參數去渲染 alert 效果。
小技巧補充 有時候我們在定義 event bus 的事件名稱及相關參數時會忘記是在哪個元件上做定義,因此我們可以利用註解的方式,將我們的定義方法寫在 bus.js 裡以方便了解。 最後,小提醒 event bus 在管理上會有些問題,能的話盡量使用在較不複雜的網頁結構上 。
參考資料 六角學院課程–Vue 出一個電商網站