深入理解Vuex 模块化(module)


Posted in Javascript onSeptember 26, 2017

一、为什么需要模块化

前面我们讲到的例子都在一个状态树里进行,当一个项目比较大时,所有的状态都集中在一起会得到一个比较大的对象,进而显得臃肿,难以维护。为了解决这个问题,Vuex允许我们将store分割成模块(module),每个module有自己的state,mutation,action,getter,甚至还可以往下嵌套模块,下面我们看一个典型的模块化例子

const moduleA = {
 state: {....},
 mutations: {....},
 actions: {....},
 getters: {....}
}

const moduleB = {
 state: {....},
 mutations: {....},
 actions: {....},
 getters: {....}
}

const store = new Vuex.Store({
 modules: {
 a: moduleA,
 b: moduleB
 }
})

store.state.a // moduleA的状态
store.state.b // moduleB的状态

二、模块的局部状态

模块内部的mutation和getter,接收的第一参数(state)是模块的局部状态对象,rootState

const moduleA = {
 state: { count: 0},
 mutations: {
 increment (state) {
  // state是模块的局部状态,也就是上面的state
  state.count++
 }
 },
 getters: {
 doubleCount (state, getters, rootState) {
  // 参数 state为当前局部状态,rootState为根节点状态
  return state.count * 2
 }
 },
 actions: {
 incremtnIfOddRootSum ( { state, commit, rootState } ) {
  // 参数 state为当前局部状态,rootState为根节点状态
  if ((state.cont + rootState.count) % 2 === 1) {
  commit('increment')
  }
 }
 }
}

三、命名空间(这里一定要看,不然有些时候会被坑)

上面所有的例子中,模块内部的action、mutation、getter是注册在全局命名空间的,如果你在moduleA和moduleB里分别声明了命名相同的action或者mutation或者getter(叫some),当你使用store.commit('some'),A和B模块会同时响应。所以,如果你希望你的模块更加自包含和提高可重用性,你可以添加namespaced: true的方式,使其成为命名空间模块。当模块被注册后,它的所有getter,action,mutation都会自动根据模块注册的路径调用整个命名,例如:

const store = new Vuex.Store({
 modules: {
 account: {
  namespaced: true,
  state: {...}, // 模块内的状态已经是嵌套的,namespaced不会有影响
  getters: {  // 每一条注释为调用方法
  isAdmin () { ... } // getters['account/isAdmin']
  },
  actions: {
  login () {...} // dispatch('account/login')
  },
  mutations: {
  login () {...} // commit('account/login')
  },
  modules: {  // 继承父模块的命名空间
  myPage : {
   state: {...},
   getters: {
   profile () {...}  // getters['account/profile']
   }
  },
  posts: { // 进一步嵌套命名空间
   namespaced: true,
   getters: {
   popular () {...} // getters['account/posts/popular']
   }
  }
  }
 }
 }
})

启用了命名空间的getter和action会收到局部化的getter,dispatch和commit。你在使用模块内容时不需要再同一模块内添加空间名前缀,更改namespaced属性后不需要修改模块内的代码。

四、在命名空间模块内访问全局内容(Global Assets)

如果你希望使用全局state和getter,roorState和rootGetter会作为第三和第四参数传入getter,也会通过context对象的属性传入action若需要在全局命名空间内分发action或者提交mutation,将{ root: true }作为第三参数传给dispatch或commit即可。

modules: {
 foo: {
 namespaced: true,
 getters: {
  // 在这个被命名的模块里,getters被局部化了
  // 你可以使用getter的第四个参数来调用 'rootGetters'
  someGetter (state, getters, rootSate, rootGetters) {
  getters.someOtherGetter // -> 局部的getter, ‘foo/someOtherGetter'
  rootGetters.someOtherGetter // -> 全局getter, 'someOtherGetter'
  }
 },
 actions: {
  // 在这个模块里,dispatch和commit也被局部化了
  // 他们可以接受root属性以访问跟dispatch和commit
  smoeActino ({dispatch, commit, getters, rootGetters }) {
  getters.someGetter // 'foo/someGetter'
  rootGetters.someGetter // 'someGetter'
  dispatch('someOtherAction')  // 'foo/someOtherAction'
  dispatch('someOtherAction', null, {root: true}) // => ‘someOtherAction'
  commit('someMutation') // 'foo/someMutation'
  commit('someMutation', null, { root: true }) // someMutation
  }
 }
 }
}

五、带命名空间的绑定函数

前面说过,带了命名空间后,调用时必须要写上命名空间,但是这样就比较繁琐,尤其涉及到多层嵌套时(当然开发中别嵌套太多,会晕。。)

下面我们看下一般写法

computed: {
 ...mapState({
 a: state => state.some.nested.module.a,
 b: state => state.some.nested.module.b
 }),
 methods: {
 ...mapActions([
  'some/nested/module/foo',
  'some/nested/module/bar'
 ])
 }
}

对于这种情况,你可以将模块的命名空间作为第一个参数传递给上述函数,这样所有的绑定会自动将该模块作为上下文。简化写就是

computed: {
 ...mapStates('some/nested/module', {
 a: state => state.a,
 b: state => state.b
 })
},
methods: {
 ...mapActions('some/nested/module',[
 'foo',
 'bar'
 ])
}

六、模块重用

有时我们可能创建一个模块的多个实例,例如:

  • 创建多个store,他们共用一个模块
  • 在一个store中多次注册同一个模块

如果我们使用一个纯对象来声明模块的状态,那么这个状态对象会通过引用被共享,导致数据互相污染。
实际上Vue组件内data是同样的问题,因此解决办法也是一样的,使用一个函数来声明模块状态(2.3.0+支持)

const MyModule = {
 state () {
 return {
  foo: 'far'
 }
 }
}

七、总结

到这里模块化(module)的内容就已经讲完了,本次主要讲解了module出现的原因,使用方法,全局和局部namespaced模块命名空间,局部访问全局内容,map函数带有命名空间的绑定函数和模块的重用。

引用

https://vuex.vuejs.org Vuex官方文档

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript比较两个日期相差天数的方法
Jul 24 Javascript
基于jquery实现日历签到功能
Sep 11 Javascript
js中判断变量类型函数typeof的用法总结
Aug 09 Javascript
Javascript自定义事件详解
Jan 13 Javascript
利用js判断手机是否安装某个app的多种方案
Feb 13 Javascript
详解JavaScript 中getElementsByName在IE中的注意事项
Feb 21 Javascript
jQuery控制元素隐藏和显示
Mar 03 Javascript
微信小程序 合法域名校验出错详解及解决办法
Mar 09 Javascript
ES6实现的遍历目录函数示例
Apr 07 Javascript
jQuery实现的淡入淡出图片轮播效果示例
Aug 29 jQuery
浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验
Dec 20 Javascript
解决layui轮播图有数据不显示的情况
Sep 16 Javascript
JavaScript实现的仿新浪微博原生态输入字数即时检查功能【兼容IE6】
Sep 26 #Javascript
JavaScript实现离开页面前提示功能【附jQuery实现方法】
Sep 26 #jQuery
Vue from-validate 表单验证的示例代码
Sep 26 #Javascript
微信小程序之蓝牙的链接
Sep 26 #Javascript
jQuery EasyUI Layout实现tabs标签的实例
Sep 26 #jQuery
jQuery EasyUI开发技巧总结
Sep 26 #jQuery
jQuery 开发之EasyUI 添加数据的实例
Sep 26 #jQuery
You might like
浅谈电磁辐射对健康的影响
2021/03/01 无线电
destoon整合ucenter后注册页面不跳转的解决方法
2014/06/21 PHP
php+redis消息队列实现抢购功能
2018/02/08 PHP
Javascript学习笔记1 数据类型
2010/01/11 Javascript
jquery判断RadioButtonList和RadioButton中是否有选中项示例
2013/09/29 Javascript
JSON格式的键盘编码对照表
2015/01/29 Javascript
jQuery修改class属性和CSS样式整理
2015/01/30 Javascript
用JS实现轮播图效果(二)
2016/06/26 Javascript
获取当前月(季度/年)的最后一天(set相关操作及应用)
2016/12/27 Javascript
Angular下H5上传图片的方法(可多张上传)
2017/01/09 Javascript
一道面试题引发的对javascript类型转换的思考
2017/03/06 Javascript
完美实现js选项卡切换效果(二)
2017/03/08 Javascript
jQuery插件FusionCharts绘制的3D双柱状图效果示例【附demo源码】
2017/04/20 jQuery
AngularJS 表单验证手机号的实例(非必填)
2017/11/12 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
JS 逻辑判断不要只知道用 if-else 和 switch条件判断(小技巧)
2020/05/27 Javascript
在ironpython中利用装饰器执行SQL操作的例子
2015/05/02 Python
python单元测试unittest实例详解
2015/05/11 Python
Python操作MySQL数据库9个实用实例
2015/12/11 Python
简单了解Python中的几种函数
2017/11/03 Python
Python基础语言学习笔记总结(精华)
2017/11/14 Python
Python学生信息管理系统修改版
2018/03/13 Python
使用Python做垃圾分类的原理及实例代码附源码
2019/07/02 Python
使用Python制作表情包实现换脸功能
2019/07/19 Python
详解python内置常用高阶函数(列出了5个常用的)
2020/02/21 Python
Python生成器传参数及返回值原理解析
2020/07/22 Python
Numpy ndarray 多维数组对象的使用
2021/02/10 Python
美国顶级户外凉鞋品牌:Chacos
2017/03/27 全球购物
护理专业推荐信
2013/11/07 职场文书
酒店个人培训自我鉴定
2013/12/11 职场文书
家长会标语
2014/06/24 职场文书
4s店销售经理岗位职责
2014/07/19 职场文书
学校联谊协议书
2014/09/16 职场文书
交通事故赔偿协议书怎么写
2014/10/04 职场文书
《鲁班学艺》读后感3篇
2019/11/27 职场文书
Mysql 用户权限管理实现
2021/05/25 MySQL