当项目非常大时,如果所有的状态都集中放到一个对象中,store 对象就有可能变得相当臃肿。

为了解决这个问题,Vuex允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。

namespaced表示当前模块是否使用命名空间,如果使用的话,那么设置了namespaced属性的模块将和其它模块独立开来,调用时得指定命名空间后才可以访问得到

例如:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="./vuex.js"></script>
</head>
<body> <div id="app">
<p>count:{{count}}</p>
<p>Acount:{{Acount}}</p>
<button @click="test1">测试1</button>
<button @click="test2">测试2</button>
</div>
<script>
const moduleA ={ //子仓库a
state:{count:0},
mutations:{Aincrement(state){state.count++}},
actions:{Aincrement(context){context.commit('Aincrement')}}
} const store = new Vuex.Store({ //创建Store实例
modules:{A:moduleA},
state:{count:1},
mutations:{increment(state){state.count++}},
actions:{increment(context){context.commit('increment')}}
}) new Vue({ //创建Vue实例
el:"#app",
store, //把实例化后的store作为new Vue的一个参数
computed:{
...Vuex.mapState(['count']),
...Vuex.mapState({Acount:state=>state.A.count})
},
methods:{
...Vuex.mapActions(['increment','Aincrement']),
test1(){
this.increment();
},
test2(){
this.Aincrement();
}
}
})
</script>
</body>
</html>

我们在根仓库定义了count状态,在子仓库A也定义了一个count,然后渲染如下:

点击测试1按钮将触发根仓库的increment这个action,点击按钮2将触发子仓库A的Aincrement这个action,分别给当前仓库的count递增1

像上面例子里区分的子module,它的mutations和actions都是和根仓库的等级是一样的,如果子仓库和根仓库的mutation或者action重名了,那么就会合并为一个数字,当触发时都会执行,例如:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
</head>
<body>
<div id="app">
<p>root.no:{{no}}</p>
<p>Amodule.no:{{Ano}}</p>
<button @click="test">测试1</button>
</div>
<script>
const store = new Vuex.Store({
state:{no:100},
mutations:{
increment(state,no){state.no+=no;}
},
modules:{
A:{
state:{no:50},
mutations:{
increment(state,no){state.no+=100;}
}
}
}
})
var app = new Vue({
store,
computed:{
...Vuex.mapState({no:state=>state.no,Ano:state=>state.A.no})
},
methods:{
...Vuex.mapMutations(['increment']),
test(){
this.increment(10);
}
},
el:'#app'
})
</script>
</body>
</html>

我们点击测试1按钮时将触发根仓库和子仓库A的increment这个mutation,此时页面会将两个对应的no都分别进行更新,这样是不符合逻辑的,最好每个仓库都互不干扰

writer by:大沙漠 QQ:22969969

我们可以给子仓库定义一个namespaced属性,值为true,表示开启命名空间,这样,各个仓库间的mutation、getter就不会有冲突了,例如:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.0/dist/vuex.js"></script>
</head>
<body>
<div id="app">
<p>root.no:{{no}}</p>
<p>Amodule.no:{{Ano}}</p>
<button @click="test1">测试1</button>
<button @click="test2">测试2</button>
</div>
<script>
const store = new Vuex.Store({
state:{no:100},
mutations:{
increment(state,no){state.no+=no;}
},
modules:{
A:{
namespaced:true,
state:{no:50},
mutations:{
increment(state,no){state.no+=no;}
}
}
}
})
var app = new Vue({
el:'#app',
store,
computed:{
...Vuex.mapState({no:state=>state.no,Ano:state=>state.A.no})
},
methods:{
...Vuex.mapMutations(['increment']),
...Vuex.mapMutations('A',{incrementA:'increment'}), test1(){
this.increment(10);
},
test2(){ this.incrementA(100);
}
}
})
</script>
</body>
</html>

渲染如下:

这里虽然子仓库和根仓库都定义了increment,但是因为子仓库定义了namespaced,所以两个并不会起冲突,namespaced的作用就是将mutation和action和其它模块区分开来,引用时需要指定命名空间才可以

源码分析


module的收集是在Vuex.store()实例化时执行ModuleCollection.register()时完成的,如下:

ModuleCollection.prototype.register = function register (path, rawModule, runtime) {    //收集模块
/*略*/ // register nested modules
if (rawModule.modules) { //如果rawModule.modules存在(含有子仓库)
forEachValue(rawModule.modules, function (rawChildModule, key) {
this$1.register(path.concat(key), rawChildModule, runtime); //递归调用register()注册子仓库
});
}
};

这样就完成了模块的收集,安装模块时也会对子模块进行判断,如下:

  function installModule (store, rootState, path, module, hot) {        //安装模块
/*略*/
module.forEachChild(function (child, key) { //如果有子模版
installModule(store, rootState, path.concat(key), child, hot); //则递归调用自身
});
}

这样就完成模块的安装了。

vuex 源码分析(七) module和namespaced 详解的更多相关文章

  1. ZRender源码分析5:Shape绘图详解

    回顾 上一篇说到:ZRender源码分析4:Painter(View层)-中,这次,来补充一下具体的shape 关于热区的边框 以圆形为例: document.addEventListener('DO ...

  2. Jvm(jdk8)源码分析1-java命令启动流程详解

    JDK8加载源码分析 1.概述 现在大多数互联网公司都是使用java技术体系搭建自己的系统,所以对java开发工程师以及java系统架构师的需求非常的多,虽然普遍的要求都是需要熟悉各种java开发框架 ...

  3. jQuery 源码分析(十八) ready事件详解

    ready事件是当DOM文档树加载完成后执行一个函数(不包含图片,css等),因此它的触发要早于load事件.用法: $(document).ready(fun) ;fun是一个函数,这样当DOM树加 ...

  4. jQuery 源码分析(十一) 队列模块 Queue详解

    队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...

  5. Netty源码分析之Reactor线程模型详解

    上一篇文章,分析了Netty服务端启动的初始化过程,今天我们来分析一下Netty中的Reactor线程模型 在分析源码之前,我们先分析,哪些地方用到了EventLoop? NioServerSocke ...

  6. 10.Spark Streaming源码分析:Receiver数据接收全过程详解

    原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/)   在上一篇中介绍了Receiver的整体架构和设计原理,本篇内容主要介绍Receiver在 ...

  7. mybatis 源码分析(三)Executor 详解

    本文将主要介绍 Executor 的整体结构和各子类的功能,并对比效率: 一.Executor 主体结构 1. 类结构 executor 的类结构如图所示: 其各自的功能: BaseExecutor: ...

  8. mybatis 源码分析(八)ResultSetHandler 详解

    本篇博客就是 myabtis 系列的最后一篇了,还剩 ResultSetHandler 没有分析:作为整个 mybatis 最复杂最繁琐的部分,我不打算按步骤一次详解,因为里面的主要内容就是围绕 re ...

  9. ZRender源码分析6:Shape对象详解之路径

    开始 说到这里,就不得不提SVG的路径操作了,因为ZRender完全的模拟了SVG原生的path元素的用法,很是强大. 关于SVG的Path,请看这里: Path (英文版) 或者 [MDN]SVG教 ...

随机推荐

  1. 拎壶学python3-----(5)pycharm解决运行时少库的问题

    有时候我们运行的时候会出现如下现象 no module named requests怎么办呢? 点击设置: 安装成功后会显示如下: 怎么进行安装呢? 然后退出再运行: 发现已经没有缺少requests ...

  2. CENTOS 7 内网网段在用IP地址检测Shell脚本优化版

    脚本内容 #!/bin/bash ############################################################################# # 用途: ...

  3. 代码生成工具Database2Sharp的架构介绍

    1)代码生成工具介绍 Database2Sharp是一款代码生成工具和数据库文档生成工具,该工具从2005年开始至今,一直伴随着我们的客户和粉丝们经历着过各种各样的项目开发,在实际开发中能带来效率的提 ...

  4. git基本操作:分支管理

    一.创建测试项目 1.新建GitHub仓库 在GitHub上面新创建一个仓库,用来演示分支管理,如下图所示: 点击“Create repository”按钮创建新仓库. 2.将本地仓库项目上传到Git ...

  5. java基础(19):List、Set

    1. List接口 我们掌握了Collection接口的使用后,再来看看Collection接口中的子类,他们都具备那些特性呢? 接下来,我们一起学习Collection中的常用几个子类(List集合 ...

  6. WebService发布服务例子

    import javax.jws.WebMethod; import javax.jws.WebService; @WebService public interface WebServiceI { ...

  7. centos7 apache后台转nginx后台

    背景 一开始买完服务器装的是用apache搭的后台, 现在想使用nginx, 希望对你有参考作用 查看系统版本信息 lsb_release -a 我的版本信息是 首先关闭apache-tomcat服务 ...

  8. 证券secuerity英语secuerity安全

    中文名:证券 外文名:security.secuerity 类别:经济权益凭证统称 组成:资本证券.货币证券和商品证券 作用:用来证明持者权益的法律凭证 图集 目录 1 发展历程 ? 世界 ? 中国 ...

  9. wamp环境下composer及laravel的安装配置

    laravel: PHP Web开发框架 composer: PHP 的一个依赖管理工具.它允许你申明项目所依赖的代码库,它会在你的项目中为你安装他们. 一.composer安装 参考:Windows ...

  10. bayaim_今晚打老虎

    bayaim_2018年11月22日11:01:14 <<<--- 再牛逼的肖邦,也尼玛弹奏不出我内心的悲伤.--->>> 艹,今天想骂人,艹TMD自己,不小心把自 ...