vue 使用的是单一状态树对整个应用的状态进行管理,也就是说,应用中的所有状态都放到store中,如果是一个大型应用,状态非常多, store 就会非常庞大,不太好管理。这时vuex 提供了另外一种方式,可以把整个store 分成几个大的模块,如登录模块,用户模块等,每一个模块都有自己的state, mutation, actions ,getters , 它就相当于是一个小的store,然后我们的根store(通过new Vuex.Store 生成的store) 通过它的modules属性引入这些模块,从而我们的组件就可以使用这些modules 中状态(state).

  新建一个项目体验一下,通过vue –cli新建一个项目vuemodule, 不要忘记安装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.属性名  可以获取到,但是有modules 之后,state 被限制到login 的命名空间(模块)下,所以属性名前面必须加模块名(命名空间),组件中通过 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>

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

  4 ,通过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(“actions”), 现在有了modules, actions 也写在了module 下面(changeName 写到了login目录下的index.js中),我们仍然可以这么写,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")
}
}
}

  5, 局部参数

  虽然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>

  6, 其实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>

 转自:https://www.cnblogs.com/SamWeb/p/6590508.html

【转】vuex2.0 之 modules的更多相关文章

  1. 【15】vuex2.0 之 modules

    vue 使用的是单一状态树对整个应用的状态进行管理,也就是说,应用中的所有状态都放到store中,如果是一个大型应用,状态非常多, store 就会非常庞大,不太好管理.这时vuex 提供了另外一种方 ...

  2. Vuex2.0+Vue2.0构建备忘录应用实践

    一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...

  3. vuex2.0+两个小例子

    首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各核心概念的理解. 废话少说,直接上干货.这是官网上的一 ...

  4. Vuex2.0边学边记+两个小例子

    最近在研究Vuex2.0,搞了好几天终于有点头绪了. 首先vuex概念比较多,一定要搞懂里面的概念,可以参考官网Vuex2.0概念,我写此文的目的是希望能对前端爱好者提供个参考,加深对vuex2.0各 ...

  5. vuex2.0.0爬坑记录 -- mutations的第一个参数state不能解构

    今天在学习vuex的过程中,遇到了一个很困扰人的问题,最终利用vuex的状态快照工具logger解决了问题. 问题是这样的,我在子组件中使用了mapState()函数来将状态映射至子组件中,使子组件能 ...

  6. vuex2.0 基本使用(4) --- modules

    vue 使用的是单一状态树对整个应用的状态进行管理,也就是说,应用中的所有状态都放到store中,如果是一个大型应用,状态非常多, store 就会非常庞大,不太好管理.这时vuex 提供了另外一种方 ...

  7. vuex2.0 基本使用(1) --- state

    Vuex 的核心是 store, 它是一个通过 Vuex.Store 构造函数生成的对象.为什么它会是核心呢?因为我们调用这个构造函数创建store 对象的时候,给它传递参数中包装了state, mu ...

  8. vuex2.0源码分析

    当我们用vue在开发的过程中,经常会遇到以下问题 多个vue组件共享状态 Vue组件间的通讯 在项目不复杂的时候,我们会利用全局事件bus的方式解决,但随着复杂度的提升,用这种方式将会使得代码难以维护 ...

  9. 【13】vuex2.0 之 state

    Vuex 的核心是 store, 它是一个通过 Vuex.Store 构造函数生成的对象.为什么它会是核心呢?因为我们调用这个构造函数创建store 对象的时候,给它传递参数中包装了state, mu ...

随机推荐

  1. [从零开始搭网站三]CentOS配置JDK

    点击下面连接查看从零开始搭网站全系列 从零开始搭网站 上一章我介绍了,如何不用每次都输密码连接服务器.那么这一章终于要开始服务器的开发环境配置了. 1:先输入以下代码来检验有没有已经安装的CDK: r ...

  2. dplyr-高效的数据变换与整理工具--转载

    1.背景简介 在数据分析工作中,经常需要对原始的数据集进行清洗.整理以及变换.常用的数据整理与变换工作主要包括:特定分析变量的选取.满足条件的数据记录的筛选.按某一个或几个变量排序.对原始变量进行加工 ...

  3. springmvc源码解析(二)

    架构流程: 1.  用户发送请求至前端控制器DispatcherServlet, 2.  DispatcherServlet收到请求调用HandlerMapping处理器映射器.  处理器映射器根据请 ...

  4. Windows下的Python 3.6.1的下载与安装(适合32bits和64bits)(图文详解)

    不多说,直接上干货! 为什么,这么简单的一个python,我还要特意来写一篇博客呢? 是因为留念下,在使用了Anaconda2和Anaconda3的基础上,现在需安装python3.6.0来做数据分析 ...

  5. Javascript 常用设计模式

    转载自:https://blog.csdn.net/buptlyz/article/details/52018193 单例模式(模块模式):确保始终只创建一个实例的对象时使用的设计模式. 为什么需要采 ...

  6. Wannafly挑战赛19 B矩阵

    矩阵 思路: 预处理好前缀和,枚举上边界和下边界,将二维变成一维,用单调队列找满足题意的最小前缀 复杂度,O(r*r*c) 代码: #pragma GCC optimize(2) #pragma GC ...

  7. Codeforces 833 C - Ever-Hungry Krakozyabra

    思路: 首先,inedible tails 的个数最多为C(18+9,9)个(用隔板法),所以我们暴力出所有的 inedible tails,然后检查一下在[L, R]这段区间是否存在这个inedib ...

  8. HDU - 1400 Mondriaan's Dream

    HDU - 1400 思路: 轮廓线dp入门题 #include<bits/stdc++.h> using namespace std; #define fi first #define ...

  9. 一个sql实现查询并且插入到另一个表中

    两种不同方法,结果不同 方法一.查询的user表中3个元素,name为user表中的字段,1000,0,是往department中要赋的值(给id赋值) ,`name`,' 方法二(推荐使用方法二): ...

  10. 拒绝采样 Rejection Sampling

    2018-12-09 16:40:30 一.使用Rand7()来生成Rand10() 问题描述: 问题求解: 这个问题字节跳动算法岗面试有问到类似的,有rand6,求rand8,我想了好久,最后给了一 ...