一、什么是module?

背景:在Vue中State使用是单一状态树结构,应该的所有的状态都放在state里面,如果项目比较复杂,那state是一个很大的对象,store对象也将对变得非常大,难于管理。
module:可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。

二、怎么用module?
一般结构

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

模块内部的数据:①内部state,模块内部的state是局部的,也就是模块私有的,比如是car.js模块state中的list数据,我们要通过this.store.state.car.carGetter的结结果是undefined,而通过this.$store.state.carGetter则可以拿到。
传参:getters====({state(局部状态),getters(全局getters对象),roosState(根状态)});actions====({state(局部状态),commit,roosState(根状态)}).

三、新建一个项目体验一下,通过vue –cli新建一个项目, 不要忘记安装vuex,cnpm install vuex --save

不了解的童鞋可以看我的 ----深入理解vue脚手架vue-cli文章这里详细介绍了新建vue-cli项目
ps: 想了解更多vuex相关知识请点击vuex官网

1, 在src 目录下新一个login文件夹,在里面新建index.js 用于存放login 模块的状态。 为了简单起见,我把模块下的state, actions,mutations, getters 全放在index.js文件中。

先简单给它增加一个状态,userName: “sam”

const state = {
useName: "sam"
};
const mutations = { };
const actions = { };
const getters = { }; // 不要忘记把state, mutations等暴露出去。
export default {
state,
mutations,
actions,
getters
}
2,在src 目录下,再新建一个 store.js 这是根store, 它通过modules 属性引入 login模块。
import Vue from "vue";
import Vuex from "vuex"; Vue.use(Vuex); // 引入login 模块
import login from "./login" export default new Vuex.Store({
// 通过modules属性引入login 模块。
modules: {
login: login
}
})
3, 在main.js中引入store, 并注入到vue 根实例中。
import Vue from 'vue'
import App from './App.vue' // 引入store
import store from "./store" new Vue({
el: '#app',
store, // 注入到根实例中。
render: h => h(App)
})
4,在 app.vue 中通过computed属性获取到login下的state. 这里要注意,在没有modules 的情况下,组件中通过 this.store.state.模块名.属性名,在这里是 this.$store.state.login.userName
<template>
<div id="app">
<img src="./assets/logo.png">
<h1>{{useName}}</h1>
</div>
</template> <script>
export default {
// computed属性,从store 中获取状态state,不要忘记login命名空间。
computed: {
useName: function() {
return this.$store.state.login.useName
}
}
}
</script>

组件中成功获取到状态。项目目录和展示如下

5,通过actions, mutations 改变名字, 这就涉及到dispatch action, commit mutations, mutations 改变state.

先在login 文件夹 index.js中添加changeName action 和 change_name mutations.

const mutations = {
change_name (state, anotherName) {
state.useName = anotherName;
}
}; const actions = {
changeName ({commit},anotherName) {
commit("change_name", anotherName)
}
};

在app.vue 中添加一个按钮:<button> change to json</button>, 点击时,dispatch 一个 action. 那在组件中怎么dispatch actions 呢?

在模块中,state 是被限制到模块的命名空间下,需要命名空间才能访问。 但actions 和mutations, 其实还有 getters 却没有被限制,在默认情况下,它们是注册到全局命名空间下的,所谓的注册到全局命名空间下,其实就是我们访问它们的方式和原来没有module 的时候是一样的。比如没有module 的时候,this.store.dispatch(“changeName”), 组件中的getters, 也是通过 this.$store.getters.module中getters 来获取。

<template>
<div id="app">
<img src="./assets/logo.png">
<h1>{{useName}}</h1>
<!-- 添加按钮 -->
<div>
<button @click="changeName"> change to json</button>
</div>
</div>
</template> <script>
export default {
// computed属性,从store 中获取状态state,不要忘记login命名空间。
computed: {
useName: function() {
return this.$store.state.login.useName
}
},
methods: {   // 和没有modules的时候一样,同样的方式dispatch action
changeName() {
this.$store.dispatch("changeName", "Jason")
}
}
}
</script>
6, 局部参数

虽然dispatch action和 commit mutations 可以全局使用,但是写在module 中的actions, mutations 和getters, 它们获得的默认参数却不是全局的,都是局部的,被限定在它们所在的模块中的。比如mutations和getters 会获得state 作为第一个默认参数,这个state参数,就是限定在mutations 和getters 所在模块的state对象,login 文件夹下的mutations 和getters 只会获取到当前index.js 中的 state 作为参数 。 actions 会获得一个context 对象作为参数,这个context 对象就是当前module 的实例,module 相当于一个小store.
那么怎样才能获取到根store 中的state 和 getters 呢? Vuex 提供了 rootState, rootGetters 作为module 中 getters 中默认参数, actions中context 对象,也会多了两个属性,context.getters, context. rootState, 这些全局的默认参数,都排在局部参数的后面。

我们在store.js中添加 state, getters:

export default new Vuex.Store({
// 通过modules属性引入login 模块。
modules: {
login: login
}, // 新增state, getters
state: {
job: "web"
},
getters: {
jobTitle (state){
return state.job + "developer"
}
}
})

login 目录下的 index.js

const actions = {
// actions 中的context参数对象多了 rootState 参数
changeName ({commit, rootState},anotherName) {
if(rootState.job =="web") {
commit("change_name", anotherName)
}
}
}; const getters = {
// getters 获取到 rootState, rootGetters 作为参数。
// rootState和 rootGetter参数顺序不要写反,一定是state在前,getter在后面,这是vuex的默认参数传递顺序, 可以打印出来看一下。
localJobTitle (state,getters,rootState,rootGetters) {
console.log(rootState);
console.log(rootGetters);
return rootGetters.jobTitle + " aka " + rootState.job
}
};

app.vue 增加h2 展示 loacaJobTitle, 这个同时证明了getters 也是被注册到全局中的。

<template>
<div id="app">
<img src="./assets/logo.png">
<h1>{{useName}}</h1> <!-- 增加h2 展示 localJobTitle -->
<h2>{{localJobTitle}}</h2>
<!-- 添加按钮 -->
<div>
<button @click="changeName"> change to json</button>
</div>
</div>
</template> <script>
import {mapActions, mapState,mapGetters} from "vuex";
export default {
// computed属性,从store 中获取状态state,不要忘记login命名空间。
computed: {
...mapState({
useName: state => state.login.useName
}), // mapGeter 直接获得全局注册的getters
...mapGetters(["localJobTitle"])
},
methods: {
changeName() {
this.$store.dispatch("changeName", "Jason")
}
}
}
</script>
7, 其实actions, mutations, getters, 也可以限定在当前模块的命名空间中。只要给我们的模块加一个namespaced 属性:
const state = {
useName: "sam"
};
const mutations = {
change_name (state, anotherName) {
state.useName = anotherName;
}
};
const actions = {
changeName ({commit, rootState},anotherName) {
if(rootState.job =="web") {
commit("change_name", anotherName)
}
},
alertName({state}) {
alert(state.useName)
}
};
const getters = {
localJobTitle (state,getters,rootState,rootGetters) {
return rootGetters.jobTitle + " aka " + rootState.job
}
};
// namespaced 属性,限定命名空间
export default {
namespaced:true,
state,
mutations,
actions,
getters
}

当所有的actions, mutations, getters 都被限定到模块的命名空间下,我们dispatch actions, commit mutations 都需要用到命名空间。如 dispacth("changeName"), 就要变成 dispatch("login/changeName"); getters.localJobTitle 就要变成 getters["login/localJobTitle"]

app.vue 如下:

<template>
<div id="app">
<img src="./assets/logo.png">
<h1 @click ="alertName">{{useName}}</h1> <!-- 增加h2 展示 localJobTitle -->
<h2>{{localJobTitle}}</h2>
<!-- 添加按钮 -->
<div>
<button @click="changeName"> change to json</button>
</div>
</div>
</template> <script>
import {mapActions, mapState,mapGetters} from "vuex";
export default {
// computed属性,从store 中获取状态state,不要忘记login命名空间。
computed: {
...mapState("login",{
useName: state => state.useName
}), localJobTitle() {
return this.$store.getters["login/localJobTitle"]
}
},
methods: {
changeName() {
this.$store.dispatch("login/changeName", "Jason")
},
alertName() {
this.$store.dispatch("login/alertName")
}
}
}
</script>

有了命名空间之后,mapState, mapGetters, mapActions 函数也都有了一个参数,用于限定命名空间,每二个参数对象或数组中的属性,都映射到了当前命名空间中。

<script>
import {mapActions, mapState,mapGetters} from "vuex";
export default {
computed: {
// 对象中的state 和数组中的localJobTitle 都是和login中的参数一一对应。
...mapState("login",{
useName: state => state.useName
}),
...mapGetters("login", ["localJobTitle"])
},
methods: {
changeName() {
this.$store.dispatch("login/changeName", "Jason")
},
...mapActions('login', ['alertName'])
}
}
</script>

四、完整项目

vuex深入理解 modules的更多相关文章

  1. 074——VUE中vuex之模块化modules开发实例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. vuex 深入理解

    参考自:https://mp.weixin.qq.com/s?src=11&timestamp=1528275978&ver=922&signature=ZeHPZ2ZrLir ...

  3. vuex简单化理解和安装使用

     1.简单化理解 首先你要明白 vuex 的目的 就是为了 集中化的管理项目中 组件所有的 数据状态 (state) 0. 第一步你要明白 , store 的重要性 , store 类似一个中央基站, ...

  4. [Vuex] Split Vuex Store into Modules using TypeScript

    When the Vuex store grows, it can have many mutations, actions and getters, belonging to different c ...

  5. 简述对Vuex的理解

          1.什么是Vuex:             Vuex是一个专为Vue.js应用程序开发的状态管理模式.     2.使用Vuex的原因:             当我们遇到多个组件共享状 ...

  6. 关于vuex的理解

    刚开始学vue的时候,看到很多项目都有用vuex,抱着一种好奇的心态去看下vuex的官方文档,如下: Vuex官方文档 Vuex 是什么?Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 ...

  7. 转一篇关于vuex简单理解的文章

    学习vuex半天摸不着头脑无意间发现了这篇文章 对vuex做了一个简单的阐述比较有助于我的理解 现在分享出来希望能给一些朋友一点帮助  这个是原文地址 http://www.ituring.com.c ...

  8. Vuex的理解以及它的辅助函数

    理解:vue中的“单向数据流”,这里借用官网的图示: Vue是单向数据流,v-model只是语法糖而已.单向数据流就是:数据总是[向下传递]从父级组件传递给子组件,只能单向绑定.子组件内部不能直接修改 ...

  9. Vuex之理解Getters的用法

    一.什么是getters在介绍state中我们了解到,在Store仓库里,state就是用来存放数据,若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中.但是如果很多组件都使用 ...

随机推荐

  1. centos系统swap设置 查看swap分区的方法

    交换分区swap,意思是“交换”.“实物交易”,它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行,和Windows的虚拟内存(pagefi ...

  2. An Example of How Oracle Works

    Oracle是怎么工作的,摘自Oracle 9i的官方文档 The following example describes the most basic level of operations tha ...

  3. git clone 报错Unable to negotiate with xxx.xxx.xxx.xxx port 12345: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

    在执行git clone命令报错 Unable to negotiate with xxx.xxx.xxx.xxx port 12345: no matching key exchange metho ...

  4. Zookeeper集群方式安装

    分布式安装部署 配置系统环境变量等 /etc/profile export JAVA_HOME=/opt/app/jdk1.8.0_181 #export CLASSPATH=.:${JAVA_HOM ...

  5. oracle exadata一体机虚拟机

    14年参加partner培训的时候,拿了份oracle exadata一体机虚拟机,有兴趣的可以试试,不过比较大,压缩后10GB,解压后50GB,启动后直接可用,2RAC节点+1存储节点,环境最好内存 ...

  6. 关于使用spring mvc或者resteasy构建restful服务的差别与比较

    resteasy 是 jboss的一个开源java api for restful service(JSR 311,sun 2008年发布,最新GA版本是2.0, JAX-RS 2.0 (JSR-33 ...

  7. Java 中断异常的正确处理方式

    处理InterruptedException 这个故事可能很熟悉:你正在写一个测试程序,你需要暂停某个线程一段时间,所以你调用 Thread.sleep().然后编译器或 IDE 就会抱怨说 Inte ...

  8. Node.js初探

    1, 设计高性能.Web服务器的几个要点:事件驱动.非阻塞I/O 2,常见Web服务器架构: Web服务器的功能: 接受HTTP请求(GET.POST.DELETE.PUT.PATCH) 处理HTTP ...

  9. Docker 使用Docker-Compose编排容器

    简介: Docker Compose是一个用来定义和运行复杂应用的Docker工具.一个使用Docker容器的应用,通常由多个容器组成.使用Docker Compose不再需要使用shell脚本来启动 ...

  10. 剥开比原看代码10:比原是如何通过/create-key接口创建密钥的

    作者:freewind 比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchai ...