首頁  >  文章  >  web前端  >  vuex2.0modules詳解

vuex2.0modules詳解

小云云
小云云原創
2018-01-16 13:05:342275瀏覽

本文主要介紹了vuex2.0 之 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.list取得;②內部getter、mutation和action,仍然註冊在全域命名空間內,這是為了多模組可以同時回應同一mutation;this.$store.state.car.carGetter的結結果是undefined,而透過this.$store.state.carGetter則可以拿到。

傳參:getters====({state(局部狀態),getters(全域getters物件),roosState(根狀態)});actions====({state(局部狀態),commit,roosState(根狀態)}).

新建一個專案體驗一下,透過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>
 <p id="app">
  <img src="./assets/logo.png">
  <h1>{{useName}}</h1>
 </p>
</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 中新增一個按鈕:bb9345e55eb71822850ff156dfde57c8 change to json

在模組中,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>
 <p id="app">
  <img src="./assets/logo.png">
  <h1>{{useName}}</h1>
  <!-- 添加按钮 -->
  <p>
   <button @click="changeName"> change to json</button>
  </p>
 </p>
</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>
 <p id="app">
  <img src="./assets/logo.png">
  <h1>{{useName}}</h1>

  <!-- 增加h2 展示 localJobTitle -->
  <h2>{{localJobTitle}}</h2>
  <!-- 添加按钮 -->
  <p>
   <button @click="changeName"> change to json</button>
  </p>
 </p>
</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>
 <p id="app">
  <img src="./assets/logo.png">
  <h1 @click ="alertName">{{useName}}</h1>

  <!-- 增加h2 展示 localJobTitle -->
  <h2>{{localJobTitle}}</h2>
  <!-- 添加按钮 -->
  <p>
   <button @click="changeName"> change to json</button>
  </p>
 </p>
</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(&#39;login&#39;, [&#39;alertName&#39;])
 }
}
</script>

相关推荐:

Yii2 如何在modules中添加验证码的方法详解

yaf框架中modules下的目录,配置二级域名

JavaScript ES6中关于module语法的详解

以上是vuex2.0modules詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn