当项目非常大时,如果所有的状态都集中放到一个对象中,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. 资源推荐:PPT快闪资源合集附配套字体下载

    样例ppt下载 搜索公众号“拒收”或扫码关注公众号 回复关键字“快闪ppt”获取全部福利 本公众号只出精品,拒收劣质 或者点击菜单链接获取获取全部资源

  2. fastdfs详细安装教程

    前言 最近开始搞的项目涉及到 fastdfs,工欲善其事,必先利其器,于是我自己搭了一台 fastdfs 服务器.坑已经帮大家都踩过了.按照该教程100%能安装成功. 前期准备 一个centos7 一 ...

  3. SQL SERVER 数据库授权指定用户

    在查询分析器下运行以下语句即可: GO USE [master] GO ALTER AUTHORIZATION ON DATABASE::[数据库名] TO [用户名] GO

  4. git登陆

    git登陆 1. 执行登陆用户名和密码命令 git config --global user.email "you@example.com" git config --global ...

  5. 20个Python代码段,你需要立刻学会,好用到哭!

    Python是一种非BS编程语言.设计简单和易读性是它广受欢迎的两大原因.正如Python的宗旨:美丽胜于丑陋,显式胜于隐式. 记住一些帮助提高编码设计的常用小诀窍是有用的.在必要时刻,这些小诀窍能够 ...

  6. mybatis动态sql和分页

    mybatis动态sql foreach BookMapper.xml <select id="selectBooksIn" resultType="com.lin ...

  7. Java日期时间API系列7-----Jdk8中java.time包中的新的日期时间API类的特点

    1.不变性 新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处. 比如:LocalDateTime 2.关注点分离 新的API将人可读的日期时间和机器时间(unix timestamp ...

  8. layui常用的验证

    var LayVerifyExtend = { notnullNonnegativeInteger: function (value, item) { //value:表单的值.item:表单的DOM ...

  9. overflow-x:scroll失效问题解决

    在移动设备上设置overflow-x:scroll,大部分机型都是展示正常的,在安卓哦5.0系统上,无论怎么样滚动条都不会生效,终于找到了解决办法: display: -webkit-box; // ...

  10. ABAP动态自建表维护程序Dynamin Process

    以前经常会遇到批量上传或修改数据到自建表的需求,所以在想是否可以做一个动态的程序,所有的自建表都可以用这个动态程序来维护. 于是就打算试着写动态的程序. 程序的要求:动态显示自建表ALV 动态下载Ex ...