深入理解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 相关文章推荐
extjs 学习笔记(二) Ext.Element类
Oct 13 Javascript
基于jquery的分页控件(C#)
Jan 06 Javascript
使用delegate方法为一个tr标签加一个链接
Jun 27 Javascript
javascript表格隔行变色加鼠标移入移出及点击效果的方法
Apr 10 Javascript
网站申请不到支付宝接口、微信接口,免接口收款实现方式几种解决办法
Dec 14 Javascript
Vue.js学习示例分享
Feb 05 Javascript
简单实现jQuery轮播效果
Aug 18 jQuery
vue 中filter的多种用法
Apr 26 Javascript
微信小程序中进行地图导航功能的实现方法
Jun 29 Javascript
从零开始学习搭建React脚手架项目
Aug 23 Javascript
Node.js 如何利用异步提升任务处理速度
Jan 07 Javascript
webgl实现物体描边效果的方法介绍
Nov 27 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
解析php常用image图像函数集
2013/06/24 PHP
easyui的tabs update正确用法分享
2014/03/21 PHP
phplist及phpmailer(组合使用)通过gmail发送邮件的配置方法
2016/03/30 PHP
Javascript绝句欣赏 一些经典的js代码
2012/02/22 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
Bootstrap模态框使用详解
2017/02/15 Javascript
Async Validator 异步验证使用说明
2017/07/03 Javascript
微信小程序倒计时功能实例代码
2018/07/17 Javascript
使用vue-cli3 创建vue项目并配置VS Code 自动代码格式化 vue语法高亮问题
2019/05/14 Javascript
layui 数据表格复选框实现单选功能的例子
2019/09/19 Javascript
vue resource发送请求的几种方式
2019/09/30 Javascript
VueCli4项目配置反向代理proxy的方法步骤
2020/05/17 Javascript
JavaScript 实现拖拽效果组件功能(兼容移动端)
2020/11/11 Javascript
Python内置函数Type()函数一个有趣的用法
2015/02/18 Python
Python中super函数的用法
2017/11/17 Python
python基于物品协同过滤算法实现代码
2018/05/31 Python
Python简直是万能的,这5大主要用途你一定要知道!(推荐)
2019/04/03 Python
Python Django 简单分页的实现代码解析
2019/08/21 Python
Python @property原理解析和用法实例
2020/02/11 Python
TensorFlow Autodiff自动微分详解
2020/07/06 Python
浅谈Python爬虫原理与数据抓取
2020/07/21 Python
PyCharm最新激活码(2020/10/27全网最新)
2020/10/27 Python
python动态规划算法实例详解
2020/11/22 Python
使用 css3 transform 属性来变换背景图的方法
2019/05/07 HTML / CSS
JD Sports马来西亚:英国领先的运动鞋和运动服饰零售商
2018/03/13 全球购物
波兰化妆品和护肤品购物网站:eKobieca
2019/08/30 全球购物
《观舞记》教学反思
2014/04/16 职场文书
住宿生擅自离校检讨书
2014/09/22 职场文书
团代会闭幕词
2015/01/28 职场文书
责任书格式
2015/01/29 职场文书
2015年节能减排工作总结
2015/05/14 职场文书
增值税发票丢失证明
2015/06/19 职场文书
回复函范文
2015/07/14 职场文书
解决Golang time.Parse和time.Format的时区问题
2021/04/29 Golang
Spring Data JPA使用JPQL与原生SQL进行查询的操作
2021/06/15 Java/Android
90后经典动画片排行:《数码宝贝》第二,《小鲤鱼历险记》在榜
2022/03/18 日漫