前幾天有盆友在羣裏問,vue.$emit和$on能夠跨組件完成全局通訊,那豈不是能夠徹底代替vuex,爲啥還要用vuex呢。
這個問題就要從eventbu事件總線s和vuex起源提及了。
(趁着尤大的vue3.0還在路上,咱們來炒炒現飯)html
在好久好久之前,在Vue王國裏有一個組件塔,有一個組件家族,A,B,C,組件父親A和兒子B,C生活在不一樣的層級之間,他們相隔很是遠。vue
這個時候,父親想念兒子了,想給他寄信,怎麼辦呢?簡單!在每個子組件上都有一個props 「郵箱」,經過這個郵箱,父親能夠直接投遞郵件(data)vuex
Vue.component('blog-post', {
// 在 JavaScript 中是 camelCase 的
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})
<!-- 在 HTML 中是 kebab-case 的 -->
<blog-post post-title="我是父親的消息!"></blog-post>
複製代碼
收到父親來信後,B,C都很是高興。想給父親回話,這時白鴿使者vue.$emit出來了,子組件用vue.$emit傳遞消息,往上層傳播。
json
this.$emit("todo",{
res:"我是兒子的消息"
})
複製代碼
接到消息後,父親得對兒子傳遞過來的不一樣類型信息作出不一樣的迴應bash
this.$on('todo',function(data){
// todo
//data => 來自兒子的消息
})
複製代碼
A常常教育B和C,說兄弟之間要多聯繫,增長感情,可是$emit又只能向上層傳遞消息,住在同一層的兄弟兩又該怎麼聯繫呢?app
這時候有一個智者想到了一個方法,既然大家都用$emit這個方法,我何不直接開個順豐快遞呢? 這時候vue eventbus事件總線出來了,利用一個遊離在組件塔外的vue實例,構造了一個bus總線,兒子的消息經過$emit給bus總線.ide
B.$root.bus.$emit('todo')
複製代碼
這時候父親所獲得的消息是由bus總線發出的,並設置響應事件post
A.$root.bus.on('todo',function(){})
複製代碼
這樣父親兒子就能夠輕輕鬆鬆的聯繫了
那最關鍵的問題是,兄弟之間怎麼聯繫呢?
總線的智者這時候跳出來講,顧客就是上帝,不論是父親兒子均可以使用咱們順豐快遞總線,這樣也就實現了兄弟組件之間的通訊ui
B.$root.bus.$emit('todo')
// 兄弟C也能收到這個消息
C.$root.bus.on('todo',function(){})
複製代碼
這個時候回到本文關鍵,爲何eventBus這麼好的東西咱們還要使用vuex呢?
如下內容參照 vuex-basics-tutorial
最開始,咱們的項目多是簡簡單單這樣的 this
1. 代碼邏輯性極具降低,可閱讀性變低
2. 對於每個action父組件都須要一個on(或dispatch)一個事件來處理
3. 你將很難查找到每個事件是從哪裏觸發,滿篇都是業務邏輯
複製代碼
舉個簡單的例子。你的公司原來有一個display組件,他的做用是展示App根組件上increment的當前值。你新招了兩個新員工,給他們分配了兩個任務。
爲了防止這些問題,這個時候,國王尤小右站了出來,他藉助隔壁flux王國的思想,帶領全國的智者研究出了一個新的方式來解決這種混亂的問題。那就是vuex了。
按照定義來講
爲了解決上述問題,咱們作出了幾個有意思的改變。(state)
這樣,原有的問題就解決了,A組件和B組件訂閱的increment再也不是根組件上的數據了,而是倉庫的數據。當倉庫數據改變時,vue將自動更新到每一個訂閱了increment數據的組件上。
// 這是父級display組件
<template>
Count is {{ sharedState.counter }}
</template>
<script>
import store from '../store'
export default {
data () {
return {
sharedState: store.state
}
}
}
</script>
複製代碼
// 這是A組件
import store from '../store'
<template>
Count is {{ sharedState.counter }}
</template>
export default {
data () {
return {
sharedState: store.state
}
},
methods: {
activate () {
this.sharedState.counter += 1
}
}
}
複製代碼
// 這是B組件
import store from '../store'
export default {
data () {
return {
sharedState: store.state
}
},
methods: {
reset () {
this.sharedState.counter = 0
}
}
}
複製代碼
上述的方式就是最好的了嗎?試想當A,B在這家公司開發了無數多個reset組件和計數器組件後離職了。這時候招來了一個新的員工C,你跟C說,我想要全部的increment大小不超過100,難道C要對全部組件進行重構,判斷大小嗎,這是很是荒謬的選擇。這時候咱們引入了新的方法。(mutation)
var store = {
state: {
counter: 0
},
increment: function () {
if (store.state.counter < 100) {
store.state.counter += 1;
}
},
reset: function () {
store.state.counter = 0;
}
}
export default store
複製代碼
根據上面的衍生,vuex就慢慢成型了
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
var store = new Vuex.Store({
state: {
counter: 0
},
mutations: {
INCREMENT (state) {
state.counter ++
}
}
})
export default store
複製代碼
咱們看下這裏作了什麼樣的操做
經過長篇的分析咱們能夠得出本文結論了。