Vuex 强调使用单一状态树,即在一个项目里只有一个 store,这个 store 集中管理了项目中所有的数据以及对数据的操作行为。但是这样带来的问题是 store 可能会非常臃肿庞大不易维护,所以就需要对状态树进行模块化的拆分。

首先贴出一个逻辑比较复杂的H5项目:源码 & DEMO

该项目主要包括 banner、feeds、profile 三个部分。其中 feeds 模块最复杂,需要对数据列表进行处理,如果单条数据中是图片:1张按照屏幕宽展示;2张各占50%;3张以上采用九宫格形式展示;如果单条数据是视频,则显示播放按钮,播放一条视频时,其他视频暂停。

由于该项目数据、交互较多,我们使用 Vuex 对数据进行托管,只在 Vue 组件中保留最基本的操作。

如果不使用 Vuex,许多数据流需要通过 props 的方便向下传递,十分不便,尤其是一些跨组件的操作更加困难。使用 Vuex 后就可以将数据与操作保留在 store 中,每个组件都能轻松调用。

本项目中除了根 store 以外,还通过 module 将各组件的 store 分开管理,还不了解的同学可以往下看。

Module

首先介绍下基本的组件化规则:你可以根据项目组件的划分来拆分 store,每个模块里管理着当前组件的状态以及行为,最后将这些模块在根 store 进行组合。

const moduleA = {
state: { ... },
getters: { ... }
mutations: { ... }
}; const moduleB = {
state: { ... },
getters: { ... },
mutations: { ... },
actions: { ... }
}; const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
}); console.log(store.state.a); // moduleA 的 state

接下来看 Vuex 核心在模块化后的使用注意事项。

请参考上文 Vuex 核心知识 (2.0)

State

在 Vuex 模块化中,state 是唯一会根据组合时模块的别名来添加层级的,后面的 getters、mutations 以及 actions 都是直接合并在 store 下。

例如,访问模块 a 中的 state,要通过 store.state.a,访问根 store 上申明的 state,依然是通过 store.state.xxx 直接访问。

const moduleA = {
state: {
maState: 'A'
}
}; const moduleB = {
state: {
mbState: 'B'
}
}; const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
},
state: {
rtState: 'Root'
}
}); console.log(store.state.a.maState); // A
console.log(store.state.b.mbState); // B
console.log(store.state.rtState); // Root

Getters

与 state 不同的是,不同模块的 getters 会直接合并在 store.getters 下

const moduleA = {
state: {
count: 1
},
getters: {
maGetter(state, getters, rootState) {
return state.count + rootState.b.count;
}
}
}; const moduleB = {
state: {
count: 2
},
getters: {
mbGetter() {
return 'Hello Vuex';
}
}
}; const store = {
modules: {
a: moduleA,
b: moduleB
}
}; console.log(store.getters.maGetter); //
console.log(store.getters.mbGetter); // Hello Vuex

在上文我们介绍过 getters 的回调函数所接收的前两个参数,模块化后需要用到第三个参数——rootState。参数: 1. state,模块中的 state 仅为模块自身中的 state;2. getters,等同于 store.getters;3. rootState,全局 state。

通过 rootState,模块中的 getters 就可以引用别的模块中的 state 了,十分方便。

注意:由于 getters 不区分模块,所以不同模块中的 getters 如果重名,Vuex 会报出 'duplicate getter key: [重复的getter名]' 错误。

Mutations

mutations 与 getters 类似,不同模块的 mutation 均可以通过 store.commit 直接触发。

const moduleA = {
state: {
count: 1
},
mutations: {
sayCountA(state) {
console.log('Module A count: ', state.count);
}
}
}; const moduleB = {
state: {
count: 2
},
mutations: {
sayCountB(state) {
console.log('Module B count: ', state.count);
}
}
}; const store = {
modules: {
a: moduleA,
b: moduleB
}
}; store.commit('sayCountA'); // Module A count: 1
store.commit('sayCountB'); // Module B count: 2 

mutation 的回调函数中只接收唯一的参数——当前模块的 state。如果不同模块中有同名的 mutation,Vuex 不会报错,通过 store.commit 调用,会依次触发所有同名 mutation。

Actions

与 mutations 类似,不同模块的 actions 均可以通过 store.dispatch 直接触发。

const moduleA = {
state: {
count: 1
},
mutations: {
sayCountA(state) {
console.log('Module A count: ', state.count);
}
},
actions: {
maAction(context) {
context.dispatch('mbAction');
}
}
}; const moduleB = {
state: {
count: 2
},
mutations: {
sayCountB(state, num) {
console.log('Module B count: ', state.count+num);
}
},
action: {
mbAction({ commit, rootState }) {
commit('sayCountA');
commit('sayCountB', rootState.a.count);
}
}
}; const store = {
modules: {
a: moduleA,
b: moduleB
}
}; store.dispatch('maAction'); // Module A count: 1、Module B count: 3

从上例可以看出,action 的回调函数接收一个 context 上下文参数,context 包含:1. state、2. rootState、3. getters、4. mutations、5. actions 五个属性,为了简便可以在参数中解构。

在 action 中可以通过 context.commit 跨模块调用 mutation,同时一个模块的 action 也可以调用其他模块的 action。

同样的,当不同模块中有同名 action 时,通过 store.dispatch 调用,会依次触发所有同名 actions。

最后有一点要注意的是,将 store 中的 state 绑定到 Vue 组件中的 computed 计算属性后,对 state 进行更改需要通过 mutation 或者 action,在 Vue 组件中直接进行赋值 (this.myState = 'ABC') 是不会生效的。

感谢你的浏览,希望能有所帮助。

Vuex 模块化与项目实例 (2.0)的更多相关文章

  1. Vuex核心知识(2.0)

    Vuex 是一个专门为 Vue.js 应该程序开发的状态管理模式,它类似于 Redux 应用于 React 项目中,他们都是一种 Flux 架构.相比 Redux,Vuex 更简洁,学习成本更低.希望 ...

  2. Vuex 模块化实现待办事项的状态管理

    前言 在vue里,组件之间的作用域是独立的,父组件跟子组件之间的通讯可以通过prop属性来传参,但是在兄弟组件之间通讯就比较麻烦了.比如A组件要告诉一件事给B组件,那么A就要先告诉他们的爸组件,然后爸 ...

  3. vuex : 模块化改造

    我们知道,vuex是vue技术栈中很重要的一部分,是一个很好用的状态管理库. 如果你的项目没有那么复杂,或者对vuex的使用没有那么重度,那么,是用不着modules功能的. 但如果你写着写着就发现你 ...

  4. 一个简单的实例演示vuex模块化和命名空间

    因为Vuex Store是全局注册的,不利于较大的项目,引入模块分离业务状态和方法,引入命名空间解决不同模块内(getters,mutaions,actions)名称冲突的问题 ----------- ...

  5. vuex源码分析3.0.1(原创)

    前言 chapter1 store构造函数 1.constructor 2.get state和set state 3.commit 4.dispatch 5.subscribe和subscribeA ...

  6. Vuex模块化

    上图是vuex的结构图vuex即 store, 包含State,Action,Mutations, 每一个vue项目都需要使用vuex做组件之间的数据共享 使用场景: 数据最终存放在store的Sta ...

  7. vuex模块化。

    项目结构: 1:在src下新建目录store,然后再建storemodule.js文件,把 上篇 store.js文件抽出来: import Vue from 'vue' import Vuex fr ...

  8. vuex 快速入门( 基于vue2.0,vue1.0未知可否)

    1.原理概述 2.用户登录例子解析: 由上图可以看到: 1.组件的数据是username,我们把它以name放在state中: 2.更改name发生在mutations的回调里,事件名字是showUs ...

  9. java springmvc +spring+ mybaits 模块化开发框架 HTML5+css3.0+bootstrap响应式开发界面

    需要源码,请加QQ:858-048-581 系统模块 1.   权限管理:点开二级菜单进入三级菜单显示 角色(基础权限)和按钮权限       角色(基础权限): 分角色组和角色,独立分配菜单权限和增 ...

随机推荐

  1. 在阿里云ECS(CentOS6.5)上安装ftp

    安装vsftpd 命令: yum install vsftpd –y 结果: 创建ftp存取文件的目录,用户名,密码 命令: useradd -d /home/ftp -g ftp -s /sbin/ ...

  2. MQ-2烟雾传感器启动

    MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2).当传感器所处环境中 存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大.使用简单的电路即可将电导率的 变化 ...

  3. CentOS6.x升级MySQL版本5.1到5.6

    CentOS6.x升级MySQL版本5.1到5.6 分类: Web MySQL 2014-08-04 11:22 2813人阅读 评论(1) 收藏 举报 mysql云服务器升级centos6 有一些虚 ...

  4. StackExchange.Redis 官方文档(一) Basics

    基本使用方法: StackExchange.Redis的核心是 StackExchange.Redis 命名空间的 ConnectionMultiplexer 类;它隐藏了多服务器的实现细节.Conn ...

  5. bzoj2628: JZPSTR

    Description 问题描述 你要对一个字符串进行三种操作: 0. 在位置x_i处插入一个字符串y_i 1. 删除位置[x_i, y_i)的字符串 2. 查询位置[x_i, y_i)的字符串包含多 ...

  6. adapter中报错:Can't create handler inside thread that has not called Looper.prepare()

    http://stackoverflow.com/questions/9357513/cant-create-handler-inside-thread-that-has-not-called-loo ...

  7. Mybatis学习(6)动态加载、一二级缓存

    一.动态加载: resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 需求: 如 ...

  8. 今日头条视频Url嗅探

    1.打开http://toutiao.com/a6309254755004875010/,查看网页源代码获取videoid = 0425d8f0c2bb425d9361c0eb2eeb4f16 2.拼 ...

  9. dotnet调用node.js写的socket服务(websocket/socket/socket.io)

    https://github.com/jstott/socketio4net/tree/develop socket.io服务端node.js,.里面有js写的客户端:http://socket.io ...

  10. android 类似QQ底部输入框弹出键盘和面板冲突 布局闪动处理方案(转)

    先看下效果 差不多就是解决这种冲突,布局闪动的 作者的githup :https://github.com/Jacksgong/JKeyboardPanelSwitch Android键盘面板冲突 布 ...