一、什么是module?

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

二、怎么用module?
一般结构

  1. const moduleA = {
  2. state: { ... },
  3. mutations: { ... },
  4. actions: { ... },
  5. getters: { ... }
  6. }
  7. const moduleB = {
  8. state: { ... },
  9. mutations: { ... },
  10. actions: { ... }
  11. }
  12. const store = new Vuex.Store({
  13. modules: {
  14. a: moduleA,
  15. 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”

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

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

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

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

  1. const mutations = {
  2. change_name (state, anotherName) {
  3. state.useName = anotherName;
  4. }
  5. };
  6. const actions = {
  7. changeName ({commit},anotherName) {
  8. commit("change_name", anotherName)
  9. }
  10. };

在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 来获取。

  1. <template>
  2. <div id="app">
  3. <img src="./assets/logo.png">
  4. <h1>{{useName}}</h1>
  5. <!-- 添加按钮 -->
  6. <div>
  7. <button @click="changeName"> change to json</button>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. // computed属性,从store 中获取状态state,不要忘记login命名空间。
  14. computed: {
  15. useName: function() {
  16. return this.$store.state.login.useName
  17. }
  18. },
  19. methods: {
  20.   // 和没有modules的时候一样,同样的方式dispatch action
  21. changeName() {
  22. this.$store.dispatch("changeName", "Jason")
  23. }
  24. }
  25. }
  26. </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:

  1. export default new Vuex.Store({
  2. // 通过modules属性引入login 模块。
  3. modules: {
  4. login: login
  5. },
  6. // 新增state, getters
  7. state: {
  8. job: "web"
  9. },
  10. getters: {
  11. jobTitle (state){
  12. return state.job + "developer"
  13. }
  14. }
  15. })

login 目录下的 index.js

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

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

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

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

app.vue 如下:

  1. <template>
  2. <div id="app">
  3. <img src="./assets/logo.png">
  4. <h1 @click ="alertName">{{useName}}</h1>
  5. <!-- 增加h2 展示 localJobTitle -->
  6. <h2>{{localJobTitle}}</h2>
  7. <!-- 添加按钮 -->
  8. <div>
  9. <button @click="changeName"> change to json</button>
  10. </div>
  11. </div>
  12. </template>
  13. <script>
  14. import {mapActions, mapState,mapGetters} from "vuex";
  15. export default {
  16. // computed属性,从store 中获取状态state,不要忘记login命名空间。
  17. computed: {
  18. ...mapState("login",{
  19. useName: state => state.useName
  20. }),
  21. localJobTitle() {
  22. return this.$store.getters["login/localJobTitle"]
  23. }
  24. },
  25. methods: {
  26. changeName() {
  27. this.$store.dispatch("login/changeName", "Jason")
  28. },
  29. alertName() {
  30. this.$store.dispatch("login/alertName")
  31. }
  32. }
  33. }
  34. </script>

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

  1. <script>
  2. import {mapActions, mapState,mapGetters} from "vuex";
  3. export default {
  4. computed: {
  5. // 对象中的state 和数组中的localJobTitle 都是和login中的参数一一对应。
  6. ...mapState("login",{
  7. useName: state => state.useName
  8. }),
  9. ...mapGetters("login", ["localJobTitle"])
  10. },
  11. methods: {
  12. changeName() {
  13. this.$store.dispatch("login/changeName", "Jason")
  14. },
  15. ...mapActions('login', ['alertName'])
  16. }
  17. }
  18. </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. rsync 同步文件如何指定属主属组和权限

    rsync daemon 同步数据时,若想同时指定权限和属主属组,可以做如下配置: [test1] uid = admin gid = admin incoming chmod = Dug=rwx,D ...

  3. MySQL按指定字段自定义列表排序

    亲测实例: 1级排序:同城>异城 2级排序:未领养>以领养 3级排序:发布最新靠前 MYSQL语句如下: SELECT ura.id,ura.city,ura.uid,ura.rescue ...

  4. 搭建一个简单的svn服务器(旧)

    cenos 6.5,svnserver 1.6.11 默认可能已经安装,没有的话就: yum install svn -ysvnserver --version 创建一个svn仓库: svnadmin ...

  5. The POM for XXX is invalid, transitive dependencies (if any) will not be available解决方案

    今天,某个开发的环境在编译的时候提示警告The POM for XXX is invalid, transitive dependencies (if any) will not be availab ...

  6. ldap集成jenkins

    jenkins版本:2.5.3,ldap插件:1.15 jenkins ldap支持需要安装ldap plugin,强烈建议插件安装版本为1.15及以上(支持ldap 配置测试) 安装插件: 系统管理 ...

  7. Bugku-CTF之web基础$_GET

    Day3   web基础$_GET   http://123.206.87.240:8002/get/   打开之后是一段代码  

  8. Django 中如何让外部访问本地的静态资源

    简单使用 在Django中打开一个入口,让别人可以访问media文件 在settings中配置 MEDIA_ROOT=os.path.join(BASE_DIR,'media') 在路由中配置 fro ...

  9. HDU 6318 Swaps and Inversions(归并排序 || 树状数组)题解

    题意:一个逆序对罚钱x元,现在给你交换的机会,每交换任意相邻两个数花钱y,问你最少付多少钱 思路:最近在补之前还没过的题,发现了这道多校的题.显然,交换相邻两个数逆序对必然会变化+1或者-1,那我们肯 ...

  10. 【Finchley】【新特性】Spring Cloud Finchley 新特性

    Finchley 正式版的发布貌似经历了相当长的时间,这次的重大发布主要带来了以下 4 项重大更新. 重大更新 1.新增 Spring Cloud Gateway 组件 Spring Cloud Ga ...