Vuex is a state management pattern + library for Vue.js applications. It serves as a centralized store for all the components in an application, with rules ensuring that the state can only be mutated in a predictable fashion.html
能够理解为,Vuex 为 VUE 提供一套经过状态共享实现的组件通讯方案。vue
父组件经过 props 向子组件传值,而且监听子组件的自定义事件。git
首选通讯方式,由于它是一种低耦合的方式。但在特定场景下有几个不足:github
它是一个典型的单向数据流,父组件不能主动触发子组件的事件vue-router
非父子组件中通讯,能够经过父组件作桥梁,可是这样父组件容易变得很臃肿,被高度耦合vuex
在 Vue 1.0 中用来解决上面第一点不足redux
在 Vue 2.0 已经废弃,不建议使用。在特定场景下有几点不足:架构
传播效率比较低,组件树越深,枝叶越多,效率也会越低app
传播方向单一,实现非父子关系的组件通讯代价太大异步
Vue 2.0 废弃 dispatch 和 broadcast 时,建议使用event bus 做为一种替代方案。
它是经典的发布订阅模式。经过 Vue 实现十分简单(固然,本身实现也很容易):
// 建立消息中心 const bus = new Vue() // 假设调用双方已经约定一个名为 myEvent 消息以及传值方式 // 订阅 bus.$on('myEvent',value=>{ alert(value) }) // 发布 bus.$emit('myEvent','ok')
它是一种彻底基于事件的方式来传值,在特定场景下有点不足:
消息容易重名
为了减小消息愈来愈多,致使消息重名,应该根据不一样的通讯范围,依赖独立的消息中心,各自管理各自的消息,减小影响范围。
Multiple views may depend on the same piece of state.
操做重复且冗余,同一个状态被分散在不一样地方,不方便管理。
<div>{{shareData.a}}</div> <c1></c1> <c2></c2>
const obj = {a: 1, b: 2} new Vue({ el: 'body', data:{ shareData:obj }, compoments:{ c1:{ template:` <div>{{shareData.a}}</div> `, data(){ return { myData:1, shareData:obj } } }, c2:{ template:` <div>{{shareData.a}}</div> `, data(){ return { myData:2, shareData:obj } } } } })
父组件经过 props 传一个引用类型给子组件也能够达到一样的效果。
它像是裸奔的Vuex,只共享了状态,在复杂的场景下难以预测状态在什么状况下会发生变化,致使追踪问题困难、维护成本增长。
有待研究
和 Vuex 的原理相近,不做讨论
基于以上的一些不足,Vuex 正好能够用来解决那些痛点。
那么 Vuex 有哪些不足呢?
它是基于数据共享的,那么显而易见,共享的越多,代码的耦合度约高,这就是在使用Vuex的时候须要去平衡的地方。
在什么场景下建议使用 Vuex ?
引入 Vuex 后的会有哪些变化?
Vuex 的版本如何选择?
如何区分和理解 actions 和 mutations 的使用场景?
如何定义 state ?
经过以上的分析,能够得出一个大体的结论,Vuex 解决了其余方案没有解决的问题,其实也正好是它的应用场景 —— 两个以上组件共享数据。
官方文档这样描述了这样一个场景
Multiple views may depend on the same piece of state.
Actions from different views may need to mutate the same piece of state.
官方文档所描述的场景多组件共享数据的状况。
若是是两个非父子组件之间彻底能够用 event bus 实现。
若是应用中有一些是两个以上的组件共享数据,有些是两个非父子组件共享数据,那么,是所有用Vuex 仍是 Vuex 和 event bus 混合用呢?
若是是三个组件共享数据,而又有一个不少表单交互,是否值得为双向绑定,增长额外的代码量?
Vue 最经典的一个例子,莫过于在表单元素上作的双向绑定。
而 Vuex 核心概念是单向数据流,必须遵循
Vuex 给咱们带来一套数据管理解决方案的,同时在必定程度上牺牲掉一部分灵活性,增长了代码量。
简单的能够认为,通用组件不该该和 Vuex 关联起来,只经过 prop event 通讯
出于如下几点,最终选择了 Vuex 2.0
当前我正在使用 Vue 1.0.28 开发项目,下意识的认为 Vuex 应该和 Vue-router 同样:
This is vue-router 2.0 which works only with Vue 2.0. For the 1.x router see the 1.0 branch.
在官方资料中也没有找到相关说明提示,最后,作了一个 demo 加入 Vuex 2.0.0 和 Vue 1.0.28 一块儿运行,测试结果没有发现跨版本的兼容问题。
排除了兼容问题。
理念仍是单向数据流,
2.0 中有几个很重要的变化,使得代码结构变得更清晰:
经过 store.dispatch
触发 actions
妈妈不再用担忧我在 `methods` 中定义的方法名和 `actions` 中的重名了
(略了,有空补充)
能够看看知乎上做者的回答
区分 actions 和 mutations 并非为了解决竞态问题,而是为了能用 devtools 追踪状态变化。
事实上在 vuex 里面 actions 只是一个架构性的概念,并非必须的,说到底只是一个函数,你在里面想干吗均可以,只要最后触发 mutation 就行。异步竞态怎么处理那是用户本身的事情。vuex 真正限制你的只有 mutation 必须是同步的这一点(在 redux 里面就好像 reducer 必须同步返回下一个状态同样)。
既然设计出来,个人理解能够这样使用:
异步操做自然要定义成 action
能够把 mutation 看做单一职责,actions 是 mutation 的组合体
也就是说,若是多个函数对 state 作了一样的操做,应该把这些操做提取出来,放到 mutation 中,这些函数定义成 action
// a 模块 const a =[{ id:1, isShow:true, aName:'a1' },{ id:2, isShow:false, aName:'a2' }]; // b 模块 const b =[{ id:1, isShow:true, bName:'b1' },{ id:2, isShow:false, bName:'b2' }]; // c 模块 const b =[{ id:1, isShow:true, cName:'c1' },{ id:2, isShow:false, cName:'c2' }];
三个模块对应 id 同步 isShow 的状态,那么问题来了 state 应该怎么定义?
// 方案1 const a= null; const b= null; const c= null; const state =[{ id:1, isShow:true, aName:'a1', bName:'b1', cName:'c1' },{ id:2, isShow:false, aName:'a1', bName:'b2', cName:'c2' }] // 方案2 const a =[{ id:1, aName:'a1' },{ id:2, aName:'a2' }]; const b =[{ id:1, bName:'b1' },{ id:2, bName:'b2' }]; const c =[{ id:1, cName:'c1' },{ id:2, cName:'c2' }]; const state =[{ id:1, isShow:true },{ id:2, isShow:false }]
我会选择方案2,理由是共享该共享的,不该该共享多余的数据。
可是纠结的是方案1,维护性看上去更好,而扩展起来没有方案2灵活。
Vuex 历经了 0.x 、 1.x(没有出正式版直接跳2.0了) 到如今的2.0正式版,不说翻天覆地,却也是变化至关大。
先看了几遍 1.0 的中文文档,把单项数据流
等一些概念简单学习,把 Vuex 想干什么,能干什么以及一些理念了解下,再简单写了个例子就算是入门了。
要注意的是,中文文档不是做者翻译的,并且后续的巨大的变动没有及时更新
,固然,用它作一份中文入门资料仍是不错的。
有了以前的入门基础后,能够更好理解的英文文档的一些概念,阅读起来不会太吃力。
固然,在知乎上有一些做者关于 Vuex 的回答,对理解 Vuex 有必定的帮助。
感受 avalon = Vue + Vuex。