前几天有盆友在群里问,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
复制代码
咱们看下这里作了什么样的操做
经过长篇的分析咱们能够得出本文结论了。