vue-bus
一個 Vue.js 事件中心插件,同時支持 Vue 1.0 和 2.0
原因
Vue 2.0 重新梳理了事件系統,因爲基於組件樹結構的事件流方式實在是讓人難以理解,並且在組件結構擴展的過程中會變得越來越脆弱。雖然依然保留了父子組件間的事件流,但有諸多限制,比如不支持跨多層父子組件通信,也沒有解決兄弟組件間的通信問題。
Vue 推薦使用一個全局事件中心來分發和管理應用內的所有事件,詳見文檔。這是一個最佳實踐,同時適用於 Vue 1.0 和 2.0。你當然可以聲明一個全局變量來使用事件中心,但你如果在使用 webpack 之類的模塊系統,這顯然不合適。每次使用都手動 import 進來也很不方便,所以就有了這個插件:vue-bus
vue-bus 提供了一個全局事件中心,並將其注入每一個組件,你可以像使用內置事件流一樣方便的使用全局事件。
安裝
$ npm install vue-bus
如果在一個模塊化工程中使用它,必須要通過 Vue.use()
明確地安裝 vue-bus:
import Vue from 'vue';
import VueBus from 'vue-bus';
Vue.use(VueBus);
如果使用全局的 script 標籤,則無須如此(手動安裝)。
使用
監聽事件和清除監聽
// ...
created() {
this.$bus.on('add-todo', this.addTodo);
this.$bus.once('once', () => console.log('這個監聽器只會觸發一次'));
},
beforeDestroy() {
this.$bus.off('add-todo', this.addTodo);
},
methods: {
addTodo(newTodo) {
this.todos.push(newTodo);
}
}
觸發事件
// ...
methods: {
addTodo() {
this.$bus.emit('add-todo', { text: this.newTodoText });
this.$bus.emit('once');
this.newTodoText = '';
}
}
注意:$bus.on
$bus.once
$bus.off
$bus.emit
只是 $bus.$on
$bus.$once
$bus.$off
$bus.$emit
的別名。 詳見 API。
==========================================================
vue 事件總線問題
在main.js中,構建
eventBus = new Vue();
pageA.vue
在methods中發佈事件
eventBus.$emit('test', 123);
應該在pageB.vue生命週期creatd/mounted中觸發事件,
eventBus.$on('test', (content) => {
//content即是出過來的值
});
問題二: 跳轉路由
pageA.vue在methods中進行路由跳轉,這時候就應在該組件被銷燬之前觸發:
beforeDestroy (){
eventBus.$emit('testClick', this.msg);
},
pageB.vue:應該在pageB.vue生命週期creatd/mounted中觸發事件,
eventBus.$on('testClick', val => {
console.log(val)
});
不要忘記清除事件(要不會觸發多次);
beforeDestroy() {
eventBus.$off('testClick')
},
=======================================================================
1.組件通訊
父子組件之間傳遞數據子組件通過
props
來接受父組件傳遞的數據,在兄弟組件之間傳遞數據的話可以使用框架vuex
,對於不是龐大的單頁面應用就不太適合使用了, vue 官網提供了一種方法叫做 中央事件總線
// 新建一個 Bus.vue文件,new 一個 vue 實例導出
export default new Vue({
name: 'bus',
data () {
return {
// code
}
}
})
// 可以理解爲這是一個傳話人員
// 新建一個組件 A
<tempalte>
<button @click="sendMessage"向組件 B 發送數據</button>
</tempalte>
<script>
import Bus from 'Bus.vue'
export default {
name: 'componentA',
data () {
return {
msg: 'the message is from componentA'
}
},
methods: {
sendMessage () {
// 假設知道組件 B 有個方法叫做 inceptMessage(接收數據的方法)
// 組件 A對組件 B 說 我要通過 Bus 這個傳話員給你傳話了,你先告訴我
// 這麼理解,當組件 A 通過 Bus 傳話員去觸發inceptMessage這個方法的時候,組件 B 是可以感應到組件 A 調用了這個方法的
Bus.$emit('inceptMessage', this.msg)
// Bus 通過觸發組件 B 的inceptMessage方法將 msg 發送過去了,這個時候組件 B 還不知道組件 A 給它發送了一條數據
}
}
}
</script>
// 新建一個組件 B
<tempalte>
// 顯示組件 A 傳過來的數據
<h1>{{ fromComponentAMsg }}</h1>
</tempalte>
<script>
import Bus from 'Bus.vue'
export default {
name: 'componentB',
data () {
return {
fromComponentAMsg: ''
}
},
methods: {
},
mounted () {
// 這個時候組件 B 知道組件 A 給它傳了一條數據過來了,於是趕緊叫 Bus 這個傳話員把數據告訴它
// bus 就告訴組件 B, 組件 A 那邊通過inceptMessage傳過來一條數據叫 msg
Bus.$on('inceptMessage',(msg) => {
this.fromComponentAMsg = msg
})
}
}
</script>
2 . 組件前進刷新,後退不刷新
vue 官網給出的一個方法是通過
keep-alive
將router-view
包住就能實現組件不刷新顯示原來的數據,但是在組件中一般都是前進更新數據返回的時候不刷新保留原來的數據,增加用戶體驗,通過搜索發現了一個方法
export default {
name: 'xxx',
data () {
//...
},
deactivated () {
this.$destroy()
},
methods: {
// ...
}
}
$destroy完全銷燬一個實例。清理它與其它實例的連接,解綁它的全部指令及事件監聽器。
這樣就可以重新更新數據了