vuex深入理解 modules
一、什么是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的更多相关文章
- 074——VUE中vuex之模块化modules开发实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vuex 深入理解
参考自:https://mp.weixin.qq.com/s?src=11×tamp=1528275978&ver=922&signature=ZeHPZ2ZrLir ...
- vuex简单化理解和安装使用
1.简单化理解 首先你要明白 vuex 的目的 就是为了 集中化的管理项目中 组件所有的 数据状态 (state) 0. 第一步你要明白 , store 的重要性 , store 类似一个中央基站, ...
- [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 ...
- 简述对Vuex的理解
1.什么是Vuex: Vuex是一个专为Vue.js应用程序开发的状态管理模式. 2.使用Vuex的原因: 当我们遇到多个组件共享状 ...
- 关于vuex的理解
刚开始学vue的时候,看到很多项目都有用vuex,抱着一种好奇的心态去看下vuex的官方文档,如下: Vuex官方文档 Vuex 是什么?Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 ...
- 转一篇关于vuex简单理解的文章
学习vuex半天摸不着头脑无意间发现了这篇文章 对vuex做了一个简单的阐述比较有助于我的理解 现在分享出来希望能给一些朋友一点帮助 这个是原文地址 http://www.ituring.com.c ...
- Vuex的理解以及它的辅助函数
理解:vue中的“单向数据流”,这里借用官网的图示: Vue是单向数据流,v-model只是语法糖而已.单向数据流就是:数据总是[向下传递]从父级组件传递给子组件,只能单向绑定.子组件内部不能直接修改 ...
- Vuex之理解Getters的用法
一.什么是getters在介绍state中我们了解到,在Store仓库里,state就是用来存放数据,若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中.但是如果很多组件都使用 ...
随机推荐
- centos系统swap设置 查看swap分区的方法
交换分区swap,意思是“交换”.“实物交易”,它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行,和Windows的虚拟内存(pagefi ...
- An Example of How Oracle Works
Oracle是怎么工作的,摘自Oracle 9i的官方文档 The following example describes the most basic level of operations tha ...
- 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 ...
- Zookeeper集群方式安装
分布式安装部署 配置系统环境变量等 /etc/profile export JAVA_HOME=/opt/app/jdk1.8.0_181 #export CLASSPATH=.:${JAVA_HOM ...
- oracle exadata一体机虚拟机
14年参加partner培训的时候,拿了份oracle exadata一体机虚拟机,有兴趣的可以试试,不过比较大,压缩后10GB,解压后50GB,启动后直接可用,2RAC节点+1存储节点,环境最好内存 ...
- 关于使用spring mvc或者resteasy构建restful服务的差别与比较
resteasy 是 jboss的一个开源java api for restful service(JSR 311,sun 2008年发布,最新GA版本是2.0, JAX-RS 2.0 (JSR-33 ...
- Java 中断异常的正确处理方式
处理InterruptedException 这个故事可能很熟悉:你正在写一个测试程序,你需要暂停某个线程一段时间,所以你调用 Thread.sleep().然后编译器或 IDE 就会抱怨说 Inte ...
- Node.js初探
1, 设计高性能.Web服务器的几个要点:事件驱动.非阻塞I/O 2,常见Web服务器架构: Web服务器的功能: 接受HTTP请求(GET.POST.DELETE.PUT.PATCH) 处理HTTP ...
- Docker 使用Docker-Compose编排容器
简介: Docker Compose是一个用来定义和运行复杂应用的Docker工具.一个使用Docker容器的应用,通常由多个容器组成.使用Docker Compose不再需要使用shell脚本来启动 ...
- 剥开比原看代码10:比原是如何通过/create-key接口创建密钥的
作者:freewind 比原项目仓库: Github地址:https://github.com/Bytom/bytom Gitee地址:https://gitee.com/BytomBlockchai ...