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>

四、完整项目

原文地址:https://www.cnblogs.com/Free-Thinker/p/10718574.html

时间: 2024-08-01 05:55:57

vuex深入理解 modules的相关文章

面试题:谈谈你对对vuex的理解

当面试官问我们对vuex的理解的时候,我们不能只说"vuex是一个专为vue.js应用程序开发的状态管理模式",尽量不要让面试官连续追问(总会问到自己不会的然后说你实力还差那么点来可以得降薪),应该从三个方面一次性去说清楚: 1.vuex是什么? 2.为什么要用vuex? 3.vuex的核心概念: vuex的属性: vuex的属性传值方式: 对于问题一,我们按官网的描述即可.vuex是一个专为vue.js应用程序开发的状态管理模式,它采用集中式存贮管理应用的所有组件的状态,并以相应的规

vuex的理解

希望能帮到需要的童鞋. vuex: 单一状态树,用一个对象就包含了全部的应用层级状态.作为项目的唯一一个          数据源ssot存在. state和getters   A. getters可以看作是state的计算属性.但都是写在store中,都是用来存储数据的.    (getters的意义在于,直接在store中对需要的state进行逻辑处理,而不用每个组件引用的时候 都处理一遍)   B. 在组件中都是通过计算属性获取store中的数据,而mapGetters和mapState,

Vuex深入理解

store下的index.js: 1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 4 Vue.use(Vuex) 5 6 let store = new Vuex.Store({ 7 state: { 8 count: 100 9 }, 10 mutations: { 11 addIncrement (state, payload) { 12 state.count += payload.n 13 }, 14 deIncrement (st

Vuex之理解Getters的用法

一.什么是getters在介绍state中我们了解到,在Store仓库里,state就是用来存放数据,若是对数据进行处理输出,比如数据要过滤,一般我们可以写到computed中.但是如果很多组件都使用这个过滤后的数据,比如饼状图组件和曲线图组件,我们是否可以把这个数据抽提出来共享?这就是getters存在的意义.我们可以认为,[getters]是store的计算属性. 二.操作 通过属性访问,通过方法访问: 在store\store.js import Vue from 'vue' import

vuex简单化理解

首先你要明白 vuex 的目的 就是为了 集中化的管理项目中 组件所有的 数据状态 (state) 0. 第一步你要明白 , store 的重要性 , store 类似一个中央基站,所有的信号和数据处理都必须 由 store 来处理 , store 其实本质也是一个对象 , 里面有 这 四个 必传的 属性 state actions mutations 1. state 是一个 对象 ,高于任何组件层面的对象,所以任何组件可以通过 mapState 获取到 你想要的 state 里面的数据 ,其

关于vuex自己理解的三幅图

Vue.js中学习使用Vuex详解

在SPA单页面组件的开发中 Vue的vuex和React的Redux 都统称为同一状态管理,个人的理解是全局状态管理更合适:简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取.进行修改,并且你的修改可以得到全局的响应变更.下面咱们一步一步地剖析下vuex的使用:首先要安装.使用 vuex首先在 vue 2.0+ 你的vue-cli项目中安装 vuex : npm install vuex --save 然后 在src文件目录下新建一个名为store的文件

VueJS中学习使用Vuex详解

在SPA单页面组件的开发中 Vue的vuex和React的Redux 都统称为同一状态管理,个人的理解是全局状态管理更合适:简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取.进行修改,并且你的修改可以得到全局的响应变更.下面咱们一步一步地剖析下vuex的使用: 首先要安装.使用 vuex 首先在 vue 2.0+ 你的vue-cli项目中安装 vuex : npm install vuex --save 然后 在src文件目录下新建一个名为store的

【15】vuex2.0 之 modules

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