Vuex入門教程

前言

組件化應用構建是Vue的特色之一,所以咱們在Vue的實際開發過程當中會常常須要封裝自定義組件,以提升開發的效率。 而組件在大部分狀況下並不會孤立的存在,它必然會與父組件和兄弟組件產生數據的交互。因此在這裏爲你們總結兩種組件數據交互的方式:EventBus和利用Vuex框架進行狀態管理。vue

上一篇文章介紹了若是經過EventBus在Vue自定義組件中進行事件傳遞(Vue自定義組件事件傳遞:EventBus部分),而EventBus比較適合在中小型項目中使用;若是咱們須要開發一套大型的項目,這時候咱們應該考慮使用Vuex框架來統一進行數據狀態管理。es6

爲了方便讀者理解Vuex的基本使用,我將繼續沿用上一篇文章的案例(顯然在單頁和中小型應用中,Vuex顯得不太必要),爲你們介紹Vuex的使用。vuex

爲何有EventBus還要使用Vuex

爲何咱們有EventBus了,還要使用Vuex?bash

其實在Vuex官網就有很好的解釋:Vuex官網對Vuex是什麼的解釋markdown

對於Vuex是什麼,個人理解是:app

Vuex是數據狀態管理框架,主要作到了數據和視圖層的解耦框架

而已經有EventBus咱們爲何還要使用Vuex這個問題上,個人理解是:ecmascript

咱們仔細思考一下,當咱們使用EventBus時,咱們A控件給B控件和C控件傳遞數據後,B控件通過處理又要修改傳遞過來數據,繼續通知A控件和C控件修改數據,這樣在C文件中就要多處監聽A和B的EventBus。這樣當有關於數據傳遞有bug時,咱們就很難追溯究竟是哪個環節出了問題。異步

伴隨着咱們業務的複雜程度變高,視圖的複雜度也會隨之升高,因此此時經過Vuex來對數據和視圖層解耦就顯得十分必要。ide

案例介紹(與上一篇"Vue自定義組件事件傳遞:EventBus部分"案例一致,可跳過)

本章節會有大量的代碼示例,爲了讓讀者閱讀輕鬆,作以下目錄和組件介紹。本章節主要運用了兩個子組件和一個父組件。

子組件文件名:SearchInput.vueSearchItem.vue

父組件文件名:StateView.vue

目錄結構展現:

一、SearchInput.vue

組件介紹:一個輸入框,它會onInput方法去監聽輸入內容,並調用方法,將輸入框內的數據傳遞出去。

代碼展現:

<template>
  <div>
    <input placeholder="搜索內容"  v-model="searchContent"/>
  </div>
</template>

<script type="text/ecmascript-6">
  export default{
    data(){
      return{
        searchContent:""
      }
    },
    props:{

    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>


複製代碼

SearchItem.vue

組件介紹:一個span,它主要用來接收父組件傳遞的內容和接收同胞組件輸入框傳遞的內容,並進行展現。

代碼示例:

<template>
    <span class="item">
      {{content}}
    </span>
</template>

<script type="text/ecmascript-6">
  export default{
    data(){
      return{
        content:this.itemContent
      }
    },
    props:{
      itemContent:{
        type:String,
        required:true
      }
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">
  .item
    background #f4f4f4
    padding 3px 5px
    box-sizing border-box
    display inline-block
    cursor pointer
</style>

複製代碼

StateView.vue

組件介紹:父組件,主要展現頁面和加載子組件

代碼示例:

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜索2"/>
      <search-item itemContent="熱門搜索3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'

export default{
  data () {
    return {
      content:"接收輸入框的值"
    }
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製代碼

正文

全局註冊Vuex

在開始介紹Vuex的內容前,咱們須要在全局中註冊一個Vuex對象。

查看咱們的目錄結構:

一、建立Store文件

咱們建立了一個store文件夾,專門存放各類類型的store文件。

在這咱們建立了SearchStore.js文件。它就是咱們接下來主要的主角,關於Vuex的State、Getter、Mutation、Action都會圍繞它來展開。

SearchStore.js代碼以下:

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
})

複製代碼

二、在main.js中注入SearchStore.js

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import vueResource from 'vue-resource'
import searchStore from './store/SearchStore'   //引入SearchStore.js
Vue.use(vueResource)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store:searchStore,           //注入SearchStore
  components: { App },
  template: '<App/>'
})

複製代碼

咱們在main.js中引入了SearchStore.js文件,並在Vue根組件中注入了SearchStore.js文件,所以全部的子組件都能訪問到了這個SearchStore.js這個Store。

State

State就像一個全局的數據倉,裏面存放着數據源

這句話怎麼理解呢?

不急,咱們看一個Demo例子,你就會對State一下就理解了。

咱們修改SearchStore.js的文件,給它加一個數據倉,即State:

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
  state:{
    searchContent:"這是Store的searchContent內容"
  }
})

複製代碼

而後咱們在StateView.jsSearchInput.js的mounted()生命週期中去打印SearchStore.js中的searchContent:

StateView

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜索2"/>
      <search-item itemContent="熱門搜索3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
  data () {
    return {
      content:""
    }
  },
  mounted(){
    console.log("StateView======"+this.$store.state.searchContent)   //打印SearchStore中的searchContent
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製代碼

SearchInput.js

<template>
  <div>
    <input placeholder="搜索內容" @input="sendEvent" v-model="searchContent"/>
  </div>
</template>

<script type="text/ecmascript-6">
  import searchEvent from '../event/SearchEvent'
  export default{
    data(){
      return{
        searchContent:""
      }
    },
    mounted(){
      console.log("SearchInput======"+this.$store.state.searchContent)
    },
    props:{

    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>

複製代碼

控制檯輸出結果

怎麼樣,對state有感受了嘛?

State的感覺結論:

一、state是一個數據存儲的倉庫,全部的數據源都會存放在這裏,就相似組件中的data。

二、咱們能夠明顯感受到,咱們在SearchStore.js的state中的數據,能夠在任意組件中經過this.$store.state訪問到,而不是像使用EventBus同樣,須要處處去調用$emit$on方法去監聽數據和拷貝數據副本,作到了數據和視圖層的解耦。

Getter

Getter 用來在獲取數據源的時候,對數據源進行必定的加工後再返回。

接下來咱們在SearchStore.js中加入Getter,來感覺下上面這句話所表達的意思。

SearchStore.js

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
  state:{
    searchContent:"這是Store的searchContent內容"
  },
  getters:{     //在這裏加入getter
    getSearchContent(state){       
    //咱們定義了一個getter函數,叫作gerSearchContent,它有一個參數,這個參數保存了state對象。
    //即SearchStore.js的state對象
      return "加工後的searchContent===="+state.searchContent     //模擬加工數據,並將加工後的數據返回
    }
  }
})
複製代碼

在這裏,咱們在Store的getters中定義了一個getSearchContent的函數,這個函數接收一個參數,這個參數就是咱們的state對象,在這個例子中,即:SearchStore.js的state對象。

而後咱們模擬了數據加工的過程,返回一個數據加工後的數據。

接下來,讓咱們在StateView的mounted()生命週期中,打印這個getter。

StateView.js

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜索2"/>
      <search-item itemContent="熱門搜索3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
  data () {
    return {
      content:""
    }
  },
  mounted(){
    console.log("StateView======"+this.$store.state.searchContent)   //打印SearchStore中的searchContent
    console.log("StateView======"+this.$store.getters.getSearchContent)  //打印SearchStore中的getSearchContent
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>
複製代碼

控制檯輸出的結果

Getter的感覺結論

一、getter主要用於在獲取數據時,對數據進行加工後返回。

二、與EventBus相比,經過Vuex的Getter,咱們能夠在Store中對數據作統一加工處理,利於往後的項目維護。

Mutation

對數據倉中的數據,進行修改。Mutation只支持同步方法

一樣,咱們經過在SearchStore.js加入Mutation來感覺Mutation的做用

SearchStore.js

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
  state:{
    searchContent:"這是Store的searchContent內容"
  },
  getters:{
    getSearchContent(state){
      return "加工後的searchContent===="+state.searchContent
    }
  },
  mutations:{
    changeSearchContent(state,payload){
      /**
       * 傳遞單個數據參數
       */
      state.searchContent=payload     //修改state的searchContent數據
    },
    changeSearchContentByObject(state,payload){
      /**
       * 有時候咱們須要再payload傳遞多個數據參數時,咱們能夠經過對象的方式傳遞
       */
      state.searchContent="經過Object對象來修改數據:"+payload.searchContent
    }
  }
})
複製代碼

注意:上面咱們定義了兩個Mutation方法,他們惟一的不一樣是一個接受的payload是單個參數;而在須要傳遞多個參數時,咱們能夠在payload中傳遞對象的方式,去傳遞多個參數。

接下來咱們依舊修改StateView.js。

StateView.js

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜索2"/>
      <search-item itemContent="熱門搜索3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
  data () {
    return {
      content:""
    }
  },
  mounted(){
    console.log("StateView======"+this.$store.state.searchContent)   //打印SearchStore中的searchContent
    console.log("StateView======"+this.$store.getters.getSearchContent)  //打印SearchStore中的getSearchContent
    
    //經過this.$store.commit()方法修改state的searchContent參數
    //在payload中傳遞單個參數
    this.$store.commit("changeSearchContent","StateView中修改後的SearchContent")
    console.log("StateView======"+this.$store.state.searchContent)
    
    //當須要傳遞多個參數時,咱們能夠在payload中以對象的形式傳遞
    this.$store.commit("changeSearchContentByObject",{"searchContent":"StateView中修改後的SearchContent","testVal":"testVal"})
    console.log("StateView======"+this.$store.state.searchContent)
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>
複製代碼

StateVie.js中,咱們經過this.store.commit()方法去調用mutations中的方法,它接收兩個參數:

一、第一個參數傳遞mutations中對應的方法名 二、第二個參數傳遞payload,即要傳遞的數據

控制檯輸出的結果

Mutation的感覺結論:

一、經過Mutation咱們能夠對數據倉中的數據進行修改,咱們能夠在組建中經過調用this.$store.commit()方法去調用對應的Mutation去修改數據。

二、Mutation中只能執行同步的方法,若是須要執行異步方法,咱們要使用接下來即將登場的Action。

Action

Action和Mutation相似,他們之處在於:一、Action 提交的是 mutation,而不是直接變動狀態。二、Action 能夠包含任意異步操做。

話很少說,咱們直接修改SearchStore.js文件:

SearchStore.js

import Vue from 'vue'
import vuex from 'vuex'
Vue.use(vuex)
export default new vuex.Store({
  state:{
    searchContent:"這是Store的searchContent內容"
  },
  getters:{
    getSearchContent(state){
      return "加工後的searchContent===="+state.searchContent
    }
  },
  mutations:{
    changeSearchContent(state,payload){
      /**
       * 傳遞單個數據參數
       */
      state.searchContent=payload     //修改state的searchContent數據
    },
    changeSearchContentByObject(state,payload){
      /**
       * 有時候咱們須要再payload傳遞多個數據參數時,咱們能夠經過對象的方式傳遞
       */
      state.searchContent="經過Object對象來修改數據:"+payload.searchContent
    }
  },
  actions:{
    changeSearchContentByAction(context,payload){
      /**
       * 模擬異步的過程,2000毫秒後經過commit()方法執行mumations中的changeSearchContentByObject方法改變數據
       * 一樣,payload能夠是單數據或經過對象的方式,傳遞多個數據
       * 這裏只舉例經過對象傳遞多數據的狀況
       */
      setTimeout(()=>{
        context.commit("changeSearchContentByObject",payload)
      },2000)
    }
  }
})
複製代碼

在這裏咱們模擬了異步的過程,經過調用setTimeOut()函數,在2000毫秒後經過調用commit()函數來改變searchContent數據。

接下來咱們來修改StateView.js來調用咱們剛剛寫的changeSearchContentByAction

StateView.js

<template>
  <div>
    <search-view></search-view>
    <div>
      <search-item :itemContent="content"/>
      <search-item itemContent="熱門搜索2"/>
      <search-item itemContent="熱門搜索3"/>
    </div>
    <div>{{content}}</div>

  </div>
</template>

<script type="text/ecmascript-6">
import searchView from '../components/SearchInput.vue'
import searchItem from '../components/SearchItem.vue'
import searchEvent from '../event/SearchEvent'
export default{
  data () {
    return {
      content:""
    }
  },
  mounted(){
    console.log("StateView======"+this.$store.state.searchContent)   //打印SearchStore中的searchContent
    console.log("StateView======"+this.$store.getters.getSearchContent)  //打印SearchStore中的getSearchContent
    
    //經過this.$store.commit()方法修改state的searchContent參數
    //在payload中傳遞單個參數
    this.$store.commit("changeSearchContent","StateView中修改後的SearchContent")
    console.log("StateView======"+this.$store.state.searchContent)
    
    //當須要傳遞多個參數時,咱們能夠在payload中以對象的形式傳遞
    this.$store.commit("changeSearchContentByObject",{"searchContent":"StateView中修改後的SearchContent","testVal":"testVal"})
    console.log("StateView======"+this.$store.state.searchContent)
    
    //經過Action修改數據
    this.$store.dispatch("changeSearchContentByAction",{"searchContent":"action修改後的數據"})
    setTimeout(()=>{
      console.log("5000毫秒後StateView======"+this.$store.state.searchContent)
    },5000)
    
  },
  components: {
    searchView,
    searchItem
  }
}

</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>
複製代碼

咱們在StateView.js中,經過this.$store.dispatch()函數去調用action,該函數接收兩個參數: 一、Store中Action對應的方法名 二、要傳遞的數據

** 控制檯輸出結果**

Action的感覺結論:

一、Action和Mutation相似,它只是可以處理異步的狀況,最終經過commit()函數調用Mutation去修改數據。

二、經過this.$store.dispatch()去調用Action的方法。

Module

能夠將Store模塊化,而後經過Module整合在一塊兒。

咱們若是將全部的數據都寫入一個Store的state中,這時候咱們獲取,修改數據。隨着項目不斷變大,咱們這個Store中的state和Mutation、Getter、Action的數量和Store的代碼行數就會爆炸性的增長,使得咱們的Store變得維護困難。

這時候,咱們但願把Store模塊化,例如不一樣子組件的數據抽取出來寫成單獨的一個Store。

這時候咱們就須要經過Module整合各個模塊,而後在將Store掛在在根組件下。

如今咱們再也不以SearchStore舉例了,咱們建立3個新的Store文件

一、index.js Store,主要負責整合全部的Store模塊。

二、SearchInputStore.js, 主要負責輸入框子組件SearchInput.js的數據維護

三、SearchItemStore.js,主要負責SearchItem.js子組件的數據維護

首先咱們來看SearchInputStore.js和SearchItemStore.js:

SearchInputStore.js

export default {
  state: {
    searchContent:""
  },
  getters:{
    getSearchContent(state){
      return state.searchContent;
    }
  },
  mutations:{
    changeSearchContent(state,payload){
      state.searchContent=payload
    }
  }
}
複製代碼

SearchItemStore.js

export default {
  state: {
    searchHistoryList:[]
  },
  getters:{
    getsearchHistoryList(state){
      return state.searchHistoryList;
    }
  },
  mutations:{
    changesearchHistoryList(state,payload){
      state.searchContent.push(payload)
    }
  }
}
複製代碼

這裏,咱們只是經過export default將SearchInputStore和SearchItemStore輸出。

接下來讓咱們看index.js,它將SearchInputStore.jsSearchItemStore.js整合在一塊兒

index.js

/**
 * Created by Vicky on 2018/6/22.
 */
import Vue from 'vue'
import vuex from 'vuex'
import searchInputStore from './SearchInputStore'
import searchItemStore from './SearchItemStore'
Vue.use(vuex)
export default new vuex.Store({
  modules:{
    searchInputStore:searchInputStore,
    searchItemStore:searchItemStore
  }
})

複製代碼

在index中咱們首先將SearchInputStore.jsSearchItemStore.js經過import引入,而後在Store的modules中將它們兩引入。

接下來咱們將index.js掛載在根組件下,咱們修改一下main.js:

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import vueResource from 'vue-resource'
import store from './store/index'   //引用index.js
// import searchStore from './store/SearchStore'
Vue.use(vueResource)
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,    //修改部分,簡寫
  components: { App },
  template: '<App/>'
})
複製代碼

這樣咱們就成功整合了兩個Store模塊,須要注意的是接下來咱們訪問state對象的對象時,須要加上模塊名

例如,咱們要訪問SearchInputStore的searchContent的數據時,咱們須要使用this.$store.state.searchInputStore.searchContent進行訪問。

namespaced: true

namespaced主要用於提升模塊的封裝性和複用性

咱們會遇到一個狀況,咱們不一樣模塊的Store中可能會存在相同方法名的Mutation、Getter和Action,這時候咱們調用commit()會調用全部相同方法名的Mutation;當咱們Getter方法名重複時,會報錯;當咱們調用dispatch()方法時,全部相同方法名的Action都會被執行。

這明顯是不符合常理的,它會對其餘模塊的數據形成污染和異常。但在一個大型項目中,咱們每每是多人協同開發的,因此咱們很難避免你們在未告知的狀況下,定義了相同名字的Mutation、Getter和Action。

此時,咱們就須要namespaced來幫咱們忙,以提升模塊的封裝性和複用性。

接下來咱們來修改index.jsSearchInputStore.js文件:

index.js

import Vue from 'vue'
import vuex from 'vuex'
import searchInputStore from './SearchInputStore'
import searchItemStore from './SearchItemStore'
Vue.use(vuex)
export default new vuex.Store({
  state:{
    rootVal:"根節點Store的值"
  },
  getters:{
    getRootVal(state){
      return state.rootVal
    }
  },
  mutations:{
    changeRootVal(state,payload){
        console.log("根節點Store的changeRootVal被調用了")
        state.rootVal=payload
    }
  },
  actions:{
    changeRootValByAction(context,payload){
      console.log("根節點Store的changeRootValByAction被調用了")
      context.commit("changeRootVal",payload)
    }
  },
  modules:{
    searchInputStore:searchInputStore,
    searchItemStore:searchItemStore
  }
})


複製代碼

咱們給index.js加了State、Getter和Mutation,這是爲了在後面演示子Store經過namespaced對數據模塊進行封裝後,子Store如何去訪問根Store的Getter、若是經過commit()調用根Mutation和子Mutation;如何經過dispatch()調用根Action和子Action。

SearchInputStore.js

export default {
  namespaced:true,
  state: {
    searchContent:""
  },
  getters:{
    getSearchContent(state,getters,rootState,rootGetters){
      /**
       * state 表明了當前模塊的state
       * getters 表明了當前模塊的getters
       * rootState 表明了根Store的state,即index.js的Store,但也包含它的子Store,咱們能夠經過rootState.searchInputStore訪問searchItemStore;經過rootState.rootVal訪問根模塊的State值。
       * rootGetters 表明了根Store的getters和它子Store的getter方法也會被掛載在rootGetters下,
       * 咱們能夠經過rootGetters["searchItemStore/getHistoryList"]去訪問searchItemStore模塊下的getHistoryList
       * 經過rootGetters.getRootVal去訪問根模塊的getRootVal
       */
      //經過rootState去訪問searchItemStore的State數據
      console.log(rootState.searchItemStore.searchHistoryList)
      //經過rootState去訪問index.js的State數據
      console.log(rootState.rootVal)

      //經過rootGetters去訪問searchItemStore的Getter
      console.log(rootGetters["searchItemStore/getHistoryList"])

      //經過rootGetters.getRootVal去訪問根模塊的getRootVal
      console.log(rootGetters.getRootVal)

      return state.searchContent;
    }
  },
  mutations:{
    changeSearchContent(state,payload){
      /**
       * state 表明了當前模塊的state
       * payload 表明了傳入的數據
       */
      //this.commit("searchItemStore/changeHistoryList",payload)調用SearchItemStore根模塊的changeHistoryList
      this.commit("searchItemStore/changeHistoryList",payload)
      //經過this.commit("changeRootVal",payload)調用根模塊的changeRootVal
      this.commit("changeRootVal",payload)
      console.log("changeSearchContent被調用了")
      state.searchContent=payload
    }
  },
  actions:{
    changeSearchContentByAction(context, payload){

      //調用本模塊的changeSearchContent
      context.commit("changeSearchContent",payload)
      //調用本模塊的otherAction
      context.dispatch("otherAction",payload)

      //調用根節點的Mutation和Action只須要傳入第三個參數對象,{root:true}便可
      context.commit("changeRootVal",payload,{root:true})
      //調用根節點的changeRootValByAction
      context.dispatch("changeRootValByAction",payload,{root:true})
    },
    otherAction(context,payload){
      console.log("otherAction被調用")
    }
  }
}

複製代碼

SearchItemStore

export default {
  namespaced:true,
  state: {
    searchHistoryList:["歷史記錄1"]
  },
  getters:{
    getHistoryList(state){
      return state.searchHistoryList;
    }
  },
  mutations:{
    changeHistoryList(state,payload){
      state.searchHistoryList.push(payload)
    }
  },
  actions:{
    changeHistoryListByAction(context,payload){
      context.commit(changeHistoryList,payload)
    }
  }
}

複製代碼

咱們經過namespaced:true來對模塊進行了封裝。

由於SearchInputStoreSearchItemStore被封裝了,咱們子組件應該如何去訪問SearchInputStore呢?SearchInput又如何訪問其餘被封裝模塊和根Store的State、Getter、Mutation和Action呢?

子組件如何訪問封裝的模塊(以訪問SearchInputStore爲例)

訪問State

在訪問被封裝的State數據時,咱們只須要作以下改變**(以訪問SearchInputStore的searchContent爲例)**:

this.$store.state.searchContent改變成this.$store.state.searchInputStore.searchContent

訪問Getter

(以訪問SearchInputStore的getSearchContent爲例):

this.$store.getters.getSearchContent改變成this.$store.getters["searchInputStore/getSearchContent"]

訪問Mutation

(以訪問SearchInputStore的changeSearchContent爲例):

this.commit("changeSearchContent","新數據")改變成this.$store.commit("searchInputStore/changeSearchContent","新數據")

訪問Action

(以訪問SearchInputStore的changeSearchContentByAction爲例):

this.dispatch("changeSearchContentByAction","新數據")改變成this.$store.dispatch("searchInputStore/changeSearchContentByAction","新數據")

封裝的模塊如何訪問其餘被封裝的模塊和根模塊(以訪問SearchItemStore爲例)

先讓咱們再仔細看下面的SearchInputStore的代碼:

SearchInputStore

export default {
  namespaced:true,
  state: {
    searchContent:""
  },
  getters:{
    getSearchContent(state,getters,rootState,rootGetters){
      /**
       * state 表明了當前模塊的state
       * getters 表明了當前模塊的getters
       * rootState 表明了根Store的state,即index.js的Store,但也包含它的子Store,咱們能夠經過rootState.searchInputStore訪問searchItemStore;經過rootState.rootVal訪問根模塊的State值。
       * rootGetters 表明了根Store的getters和它子Store的getter方法也會被掛載在rootGetters下,
       * 咱們能夠經過rootGetters["searchItemStore/getHistoryList"]去訪問searchItemStore模塊下的getHistoryList
       * 經過rootGetters.getRootVal去訪問根模塊的getRootVal
       */
      //經過rootState去訪問searchItemStore的State數據
      console.log(rootState.searchItemStore.searchHistoryList)
      //經過rootState去訪問index.js的State數據
      console.log(rootState.rootVal)

      //經過rootGetters去訪問searchItemStore的Getter
      console.log(rootGetters["searchItemStore/getHistoryList"])

      //經過rootGetters.getRootVal去訪問根模塊的getRootVal
      console.log(rootGetters.getRootVal)

      return state.searchContent;
    }
  },
  mutations:{
    changeSearchContent(state,payload){
      /**
       * state 表明了當前模塊的state
       * payload 表明了傳入的數據
       */
      //this.commit("searchItemStore/changeHistoryList",payload)調用SearchItemStore根模塊的changeHistoryList
      this.commit("searchItemStore/changeHistoryList",payload)
      //經過this.commit("changeRootVal",payload)調用根模塊的changeRootVal
      this.commit("changeRootVal",payload)
      console.log("changeSearchContent被調用了")
      state.searchContent=payload
    }
  },
  actions:{
    changeSearchContentByAction(context, payload){

      //調用本模塊的changeSearchContent
      context.commit("changeSearchContent",payload)
      //調用本模塊的otherAction
      context.dispatch("otherAction",payload)

      //調用根節點的Mutation和Action只須要傳入第三個參數對象,{root:true}便可
      context.commit("changeRootVal",payload,{root:true})
      //調用根節點的changeRootValByAction
      context.dispatch("changeRootValByAction",payload,{root:true})
    },
    otherAction(context,payload){
      console.log("otherAction被調用")
    }
  }
}
複製代碼
訪問State和Getter

先看SearchInputStore的getters:

咱們發現getSearchContent接受的參數從state變成了state,getters,rootState,rootGetters,它們的含義以下:

一、state 表明了當前模塊的state

二、getters 表明了當前模塊的getters

三、rootState 表明了根Store的state,即index.js的Store,但也包含它的子Store,咱們能夠經過rootState.searchInputStore訪問searchItemStore;經過rootState.rootVal訪問根模塊的State值。

四、rootGetters 表明了根Store的getters和它子Store的getter方法也會被掛載在rootGetters下,咱們能夠經過rootGetters["searchItemStore/getHistoryList"]去訪問searchItemStore模塊下的getHistoryList

訪問Mutation

(以訪問SearchInputStore的changeSearchContent爲例):

在SearchInputStore的Mutation中能夠經過:

一、this.commit("searchItemStore/changeHistoryList",payload)調用SearchItemStore根模塊的changeHistoryList

二、this.commit("changeRootVal",payload)調用根模塊的changeRootVal

訪問Action

(以訪問SearchInputStore的changeSearchContentByAction爲例):

在SearchInputStore的Action中能夠調用根模塊的Mutation和Action,但不能調用其它封裝模塊的Mutation,不然會報錯。

其實這也是有道理的,當咱們本模塊的Mutation異步執行完畢,想要去修改其餘模塊的數據,只須要在本身模塊的Mutation去調用其餘模塊的Mutation便可,沒有必要再去調用其餘模塊的Action。

所以咱們能夠在本模塊中經過context.commit()cotext.dispatch()去調用本模塊和根模塊的Mutation和Action:

一、調用本模塊的changeSearchContent:context.commit("changeSearchContent",payload)

二、 調用本模塊的otherAction:context.dispatch("otherAction",payload)

三、調用根模塊的Mutation和Action只須要傳入第三個參數對象,{root:true}便可:context.commit("changeRootVal",payload,{root:true})

四、調用根模塊的changeRootValByAction:context.dispatch("changeRootValByAction",payload,{root:true})

最後覆盤

一、Vuex是數據和視圖層解耦的框架

二、在單頁和小項目中沒有必要使用Vuex。

三、Vuex中的State就像一個全局的數據倉,裏面存放着數據源。

四、Vuex中的Getter 用來在獲取數據源的時候,對數據源進行必定的加工後再返回。

五、Vuex中的Mutation用來對數據倉中的數據,進行修改。Mutation只支持同步方法。

六、Vuex中的Action和Mutation相似,他們之處在於:一、Action 提交的是 mutation,而不是直接變動狀態。二、Action 能夠包含任意異步操做。

七、Vuex中的Module能夠將Store模塊化,而後經過Module整合在一塊兒。

八、關於...mapGetters、...mapMutation、...mapActions具體不展開,主要是經過es6的語法簡化代碼書寫,能夠參考官方文檔: Vuex官方文檔

九、看完本教程,因爲內容較多,建議本身再看一次官方文檔,並本身實現一個小Demo

我是大麥,若是喜歡個人文章,請給我一顆當心心。

相關文章
相關標籤/搜索