Vue进阶篇-Vue的大型数据中心vuex

vue在进行组建开发过程中,本组建直接操作数据实现数据绑定,父子组件传递通过传参和外传方式传递,在多层组件和同级组件开发过程中,小范围数据状态管理使用vue-bus,或者直接自行建立一个全局变量进行操作。vue的数据通信有时候还是很令人崩溃的。 在进行更大范围vue状态管理或者数据管理时,就可以使用vuex,官方提供的vue集中式状态管理工具了。所以,如果你的应用很简单,就不要用vuex。
安装使用
直接使用命令进行安装 npm install vuex –save 然后在main.js中加入包的使用:
import vuex from \'vuex\' Vue.use(vuex); var store = new vuex.Store({//store对象 state:{ count:0 } }) new Vue({ el: \'#app\', router, store,//使用store template: \'\', components: { App } })
然后就可以在需要的地方使用 $store.state.count 了。 当然这是最最简单的应用,数据模块拆分比较多,想看起来结构清晰的话,也可以进行拆分,拆分之前,先理解了解下vuex里面的核心概念。
核心概念
任何状态管理或者数据存储的工具,无非就是分为把数据存进去的过程,数据本身,数据输出展示过程,vuex也不例外。上个图,可能跟想象的不太一样

存储过程: Actions,数据存储进去的前置,操作Mutation,可忽略。 Mutation,唯一可以直接操作State的部分。 数据本身: State,就属于存储的数据本身了。 Getter,State数据本身可以通过计算进行衍生的数据。 数据取出展示: 数据取出部分就直接在需要的板块进行使用就可以了。通常会在组件的计算属性computed中可以进行进一步过滤操作,然后输出到页面上来。 其他: Module,vuex由于使用的是单一状态数结构,数据较多时,进行模块拆分时使用。对应里面的所有的部分 state,getter,action,mutation都可以拆分到模块里面去。 了解完核心概念之后,针对复杂应用,我们就可以把store拆掉了。在src文件夹下面新建store文件夹,下方将vuex的每个模块都进行拆分,因为每个模块都有可能会有一大堆数据。
import Vue from \'vue\' import Vuex from \'vuex\' import state from \'./state\' import mutations from \'./mutations\' import add from \'./module/add\' Vue.use(Vuex) export default new Vuex.Store({ state, mutations, modules: { a:add } })
对应main.js的引用就变化了。
import store from \'./store\' new Vue({ el: \'#app\', router, store,//使用store template: \'\', components: { App } })
对应的文件结构就变成如下

下面是里面细节板块的使用了。
State
state属于数据中心,内容来源数据初始化,变更来自于mutations,读取的话,通常使用computed属性进行读取。state里面内容变更后会触发计算属性重新获取,并且同步渲染到页面中。
// 创建一个 Counter 组件 const Counter = { template: `
`, computed: { count () { return this.$store.state.count } } }
多条state读取的时候,引入mapState辅助函数。使用之前要import。 然后在需要的时候直接引入一个数组。
computed: { ...mapState([\'count\']) }
如果引入的元素需要过滤的话,就可以单独处理。 这里要提供一个初始化时候来源数据,可以拓展很多东西,比如来自localStage,database等等。
Getter
Getter是State元素的派生元素。跟vue里面的computed功能差不多。某些通过计算或者过滤State里面的元素就可以得到的元素,就可以直接使用getter来生成。 举个例子,在State里面存储了一堆学生的成绩,这个时候,就可以使用getter设置计算出对应学生的个数,成绩的总和,平均值,几个及格,几个优秀。在添加新的学生成绩之后,对应的这些数值就都会同步的进行刷新。 当然,上面问题会有很多中方式解决这种问题,上面只是举个这个例子。下面代码的案例就todolist案例,state中只存储所有的数据,对应的过滤元素都可以在getter中取得,代码中放一个计算属性是doneTodos就是过滤之后的元素,在展示的时候,直接使用就可以了 设置方法:
const store = new Vuex.Store({ state: { todos: [ { id: 1, text: \'...\', done: true }, { id: 2, text: \'...\', done: false } ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } })
在使用的时候,同State类似,直接使用this.$store.getters.doneTodos,就可以了。 getter取值的时候,也可以传递参数进去。
getters: { // ... getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, text: \'...\', done: false }
这里,针对访问多个计算属性getter也有一个辅助函数,mapGetters。使用方法类似,也要先引用,后加入computed
export default { // ... computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ \'doneTodosCount\', \'anotherGetter\', // ... ]) } }
Mutation
Mutation是同步操作state改变唯一的区域,这里操作state中间再去操作点其他事情就看你自己了,比如变化同步写入localstage,方便浏览器刷新,state取默认值的时候,就可以使用本地数据了,达到优化体验的效果。 基本用例:
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state, n) { // 变更状态 state.count = n } } }) store.commit(\'increment\',n)
提交的方法可以增加参数,参数就参数,官方非要起个载荷(Payload)的名字,不知道为啥。 需要注意的是,mutations必须是同步的操作。 不过,在mutation里面执行异步操作会怎么样呢?好像也没有发生什么奇怪的事情。官方是建议这么做了。
Action
在进行多个mutation操作state时,维护起来比较麻烦,就用到了action的功能。action操作的是mutation,而且是可以包含任意的异步操作。
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count } }, actions: { increment (context) { context.commit(\'increment\') } } })
同样,action也有对应的mapAction辅助函数,功能一样的。
Module
各种方法,生成,数据较多的时候,方便管理就可以使用Module进行模块的拆分。
const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的状态 store.state.b // -> moduleB 的状态
不过,getter,action,mutation默认情况下都是注册在全局命名下。同名的方法在不同模块下调用,会整体进行响应。然后可以通过namespaced: true,和root:true在模块命名的时候全局的变局部的,局部里面声明全局的,来回折腾。
{ actions: { someOtherAction ({dispatch}) { dispatch(\'someAction\') } }, modules: { foo: { namespaced: true, actions: { someAction: { root: true, handler (namespacedContext, payload) { ... } // -> \'someAction\' } } } } } computed: { ...mapState({ a: state => state.some.nested.module.a, b: state => state.some.nested.module.b }) }, methods: { ...mapActions([ \'some/nested/module/foo\', // -> this[\'some/nested/module/foo\']() \'some/nested/module/bar\' // -> this[\'some/nested/module/bar\']() ]) }
由于这一块儿我也没用过,你自行理解吧。更多的还有涉及到动态注册、模块重用等等,插件编写等等。 整个介绍完之后放上官方推荐的文件结构,购物车的例子
|── index.html ├── main.js ├── api │ └── ... # 抽取出API请求 ├── components │ ├── App.vue │ └── ... └── store ├── index.js # 我们组装模块并导出 store 的地方 ├── actions.js # 根级别的 action ├── mutations.js # 根级别的 mutation └── modules ├── cart.js # 购物车模块 └── products.js # 产品模块
vue-devtools
vue开发强烈推荐使用的浏览器插件工具。尤其可以看到vuex里面这些元素的变化。并且每一步操作之前产生的影响都可以直观的看出来。回头单独介绍安装使用截图等。
文末
到这里,差不多vuex常用的东西都介绍完了。这个能大致了解,就可以去通读vuex的官方文档了。还是要强调,如果你涉及到的数据量比较小,状态管理的东西较少,就不建议使用vuex了。