匯流排傳值有兩種寫法:原型bus寫法【 window.Vue.prototype.bus = new Vue() 】、全域性bus寫法【 window.bus=new Vue() 】。
如果使用了原型寫法,那在元件裡面必須使用 this.bus.$emit() 傳送訊息,以及使用 this.bus.$on() 接收訊息。它們全部要用 this 開頭。如果使用了全域性寫法,則可以簡化為 bus.$emit() 及 bus.$on() 了。
在確保全域性bus不會發生變數名稱衝突的前提下,使用全域性bus的寫法要更簡單一些。首先,修改 resources\assets\js\app.js 檔案引入全域性bus
require('./bootstrap');
window.Vue = require('vue');
window.bus=new Vue(); //全域性bus
// window.Vue.prototype.bus = new Vue(); //原型bus
import ...
const app = new Vue({
el: '#app',
components:{
...
},
});
這裡需要注意的是window.bus=new Vue() 這行程式碼的位置有講究,不能把它放在 const app=new Vue({...}); 之後。
在blade模板中,以下兩個Vue元件是同級關係
<cart-items :items="{{$cartItems}}" ></cart-items>
<cart-selected></cart-selected>
元件1的作用:
1、接收資料庫查詢到的複雜物件 $cartItems
2、根據使用者的勾選或刪除等操作進行加工處理,得到特定資料data
3、加工完畢,傳送一個訊息msg_SelectedItemChange 並對外傳遞資料data
元件1傳送資料的程式碼很簡單,只需一行bus.$emit('msg_SelectedItemChange', data)
元件2的作用:
1、接收元件1加工後的資料data
2、將此資料重新整理到瀏覽器裡(或者等待使用者點選提交按鈕傳送ajax請求等等)
元件2接收資料稍微麻煩一點,因為需要使用一個回撥函式,大致如下bus.$on('msg_SelectedItemChange', 回撥函式的名稱)
難點在於回撥函式內部的this指向可能有問題,比如下面的寫法就不能在瀏覽器裡面顯示元件2獲取的資料
<template>
<div>元件2:{{cartItems}}</div>
</template>
<script>
export default {
name: "CartSelected",
data(){
return{
cartItems:[],
}
},
mounted(){
bus.$on('msg_SelectedItemChange', function(data){
this.cartItems=data; //無效,因為this指向的已經不是本元件了!
})
},
}
</script>
嘗試使用call()重定向回撥函式內部的this指向也是無效的
mounted(){
bus.$on.call(this, 'msg_SelectedItemChange', function(data){
this.cartItems=data; //也無效
})
},
改用that重定向,有效!
mounted(){
let that=this;
bus.$on('msg_SelectedItemChange', function(data){
that.cartItems=data; //有效,匿名函式使用that重定向到本元件
})
},
改用立即執行函式並返回一個閉包函式的寫法也是有效的,可惜晦澀得很,寫起來也麻煩。閉包函式既能訪問形參it又能訪問that變數,使用任何一個都可以完成任務,唯獨不能使用this
mounted(){
let that=this;
bus.$on('msg_SelectedItemChange', function(it){
return function(data){
that.cartItems=data; // OK
it.cartItems=data; // OK too
this.cartItems=data; // Bad
}
}(this))
},
使用bind重定向(很簡潔的寫法)
雖然that重定向的寫法也很簡潔,但是函式體裡面的this必須全部改用that替換。使用bind則無需替換,剛好解決了這一缺陷。
mounted(){
bus.$on('msg_SelectedItemChange', function(data){
this.cartItems=data;
}.bind(this))
},
也可以採用一種很標準的寫法(往methods物件裡面插入一個新方法)。此法不夠簡潔,但是比較靈活,可以隨時呼叫refresh()方法。
methods:{
refresh(data){
this.cartItems=data;
}
},
mounted(){
bus.$on('msg_SelectedItemChange', this.refresh)
},
下面是第5種,使用箭頭函式的寫法(比bind還要簡潔)
mounted(){
bus.$on('msg_SelectedItemChange', data=>
this.cartItems=data
)
},
本作品採用《CC 協議》,轉載必須註明作者和本文連結