作者:小土豆
掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d
微信公眾號:不知名寶藏程序媛(關注"不知名寶藏程序媛"免費領取前端電子書籍。文章公眾號首發,關注公眾號第一時間獲取最新文章。)
碼字不易,點贊鼓勵喲~
Vuex系列文章
《Vuex實踐(中)-多module中的state、mutations、actions和getters》
《Vuex實踐(下)-mapState和mapGetters》
一.前言
本文章是vuex系列的最后一篇,主要總結的是如何使用mapState和mapGetters訪問vuex中的state和getters。
二.多個模塊中mapState和mapGetters的使用
上一篇文章《Vuex實踐(中)》里面我們總結的就是多模塊的內容,所以關於store.js、moduleA.js和moduleB.js的代碼保持不變。
在此為了方便觀看,我將這三個文件的代碼在貼在這里
E:\MyStudy\test\VueDemo\src\vuex\store.js
1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 import moduleA from './moduleA' 4 import moduleB from './moduleB' 5 6 Vue.use(Vuex) 7 8 export default new Vuex.Store({ 9 state: { 10 counter: 1000 11 }, 12 mutations: { 13 //遞增 14 increase(state) { 15 console.log("store-increase") 16 state.counter++ 17 }, 18 //遞減 19 decrement(state) { 20 state.counter-- 21 } 22 }, 23 actions: { 24 increaseAction(context) { 25 setTimeout(function(){ 26 //action通過提交mutation改變共享數據狀態 27 context.commit('increase'); 28 },3000) 29 }, 30 decrementAction(context){ 31 setTimeout(function(){ 32 //action通過提交mutation改變共享數據狀態 33 context.commit('decrement'); 34 },3000) 35 } 36 }, 37 getters: { 38 doubleCounter(state) { 39 return state.counter*state.counter 40 } 41 }, 42 modules: { 43 a: moduleA, 44 b: moduleB 45 } 46 })
E:\MyStudy\test\VueDemo\src\vuex\moduleA.js
const moduleA = { namespaced: true, state:{ counter: 100 }, mutations: { //遞增 increase(state) { console.log("moduleA-increase") state.counter++ }, //遞減 decrement(state) { state.counter-- } }, actions: { increaseAction(context) { setTimeout(function(){ //action通過提交mutation改變共享數據狀態 context.commit('increase'); },3000) }, decrementAction(context){ setTimeout(function(){ //action通過提交mutation改變共享數據狀態 context.commit('decrement'); },3000) } }, getters: { doubleCounter(state) { return state.counter*state.counter } } } export default moduleA
E:\MyStudy\test\VueDemo\src\vuex\moduleB.js
1 const moduleB = { 2 namespaced: true, 3 state:{ 4 counter: 5 5 }, 6 mutations: { 7 //遞增 8 increase(state) { 9 console.log("moduleB-increase") 10 state.counter++ 11 }, 12 //遞減 13 decrementAction(state) { 14 state.counter-- 15 } 16 }, 17 actions: { 18 increaseAction(context) { 19 setTimeout(function(){ 20 //action通過提交mutation改變共享數據狀態 21 context.commit('increase'); 22 },3000) 23 }, 24 decrementAction(context){ 25 setTimeout(function(){ 26 //action通過提交mutation改變共享數據狀態 27 context.commit('decrement'); 28 },3000) 29 } 30 }, 31 getters: { 32 doubleCounter(state){ 33 return state.counter*state.counter 34 } 35 } 36 } 37 38 export default moduleB
現在需要在組件中使用mapState和mapGetters
還是按照之前的套路
在App.vue組件中訪問根根模塊store和a模塊moduleA的state和getters。
在Index.vue組件中訪問b模塊moduleB的state和getters
1.使用mapState
使用mapState訪問state的寫法也有多種,我們一個一個來實踐(不包含es6的寫法)
[第一種寫法]
E:\MyStudy\test\VueDemo\src\App.vue
<template> <div id="app"> <img src="./assets/logo.png"> <!-- 獲取共享數據 --> <h1>這里是App組件</h1> <h3> App組件獲取共享數據 </h3> <h3>使用mapState訪問根組件counter : {{counter}}</h3> <h3>使用mapState訪問a組件counter : {{counterA}}</h3> <hr/> <Index></Index> </div> </template> <script> import Index from './components/Index' import { mapState } from 'vuex' export default { name: 'App', components: { Index }, computed: mapState({ //訪問store根模塊 counter: function(state){ return state.counter }, //訪問a模塊 counterA: function(state){ return state.a.counter } }) } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
E:\MyStudy\test\VueDemo\src\components\Index.vue
<template> <div> <h1>這里是Index.vue組件</h1> <h3>Index組件獲取共享數據 </h3> <h3>使用mapState訪問b模塊counter :{{ counterB }}</h3> </div> </template> <script> import { mapState } from 'vuex' export default { name: 'Index', computed: mapState({ counterB: function(state){ return state.b.counter } }) } </script>
在App.vue、Index.vue組件中使用mapState,首先第一步需要引入mapState。
接着就是在計算屬性computed中使用,以Index.vue中的代碼為例
computed: mapState({ counterB: function(state){ return state.b.counter } })
可以看到mapState關聯到vue的計算屬性中。
獲取b模塊的state,只需要以vue計算屬性的形式在函數中返回state.b.counter即可。
(獲取根模塊state返回state.counter;獲取a模塊state返回state.a.counter)
這樣在模板中就可以使用計算屬性的語法訪問state
備注:這種方式,當注釋掉命名空間的配置后,依然可以正常訪問到不同模塊的state
[第二種寫法]
第二種寫法和第一種有些類似,只是以字符串的形式返回計算屬性。
我們先在Index.vue組件中訪問b模塊的數據。
E:\MyStudy\test\VueDemo\src\components\Index.vue
1 <template> 2 <div> 3 <h1>這里是Index.vue組件</h1> 4 <h3>Index組件獲取共享數據 </h3> 5 <h3>使用mapState訪問b模塊counter :{{ counterB }}</h3> 6 </div> 7 </template> 8 <script> 9 import { mapState } from 'vuex' 10 export default { 11 name: 'Index', 12 computed: mapState('b',{ 13 counterB: 'counter' 14 }) 15 } 16 </script>
核心代碼如下
computed: mapState('b',{ counterB: 'counter' })
可以看到,mapState第一個參數限定了模塊名稱。
接着就是以'counter'字符串的形式返回了b模塊的counter值。
那么根據之前一系列的總結,可知
訪問根模塊的數據,不需要限定第一個參數;
訪問a模塊的數據,需要限定第一個參數為a
然而,因為訪問根模塊和訪問a模塊同在App.vue組件中,那么因為mapState第一個參數限定的問題,我們需要編寫兩個mapState。
現在直接上代碼(只把computed中的核心代碼貼上)
E:\MyStudy\test\VueDemo\src\App.vue
computed: { ...mapState({ //訪問store根模塊 counter: 'counter', }), ...mapState('a',{ //訪問a模塊 counterA: 'counter' }) }
可以看到,我寫了兩個mapState,還是...mapState的形式。
...mapState它是ES6中擴展運算符的語法,應用在mapState上,官方文檔是這樣說的
(
此處若對此有疑問,可以在去仔細研究一下對象擴展運算符的內容。
我這里貼一個簡單的示例
最終newObj的打印結果為
相信這個示例可以很清楚的解釋我們寫的兩個...mapState的寫法
)
官方文檔處提到這個對象展開運算符的場景是為了將一個組件中原本的計算屬性和mapState混合使用
(混合使用這個點日常開發會用到,很實用的一個點)。
那本次我們也是使用這個語法成功的獲取到了不同模塊的state。
最后我們在使用瀏覽器查看一下最終App.vue和Index.vue中的結果
我們已經使用mapState成功的訪問到了多模塊中的state數據。
備注:這種關於mapState的寫法不能刪除moduleA和moduleB中關於命令空間的配置,否則會報錯。
最后作者還嘗試了一個問題,就是將moduleA.js中的state屬性改為counterA
然后修改了App.vue組件中computed訪問a模塊數據的代碼
最后發現這樣並不能正常訪問到a模塊的state數據。(刪除a模塊的命名空間配置也無法正常訪問)
這個嘗試僅給大家一個反面的示例。
2.使用mapGetters
前面使用mapState訪問了state數據,那么現在我們使用mapGetters訪問一下vuex中的getters。
在研究之后發現,暫時發現使用mapGetters訪問一下vuex中的getters只有字符串的形式。
E:\MyStudy\test\VueDemo\src\App.vue
1 <template> 2 <div id="app"> 3 <img src="./assets/logo.png"> 4 <!-- 獲取共享數據 --> 5 <h1>這里是App組件</h1> 6 <h3> App組件獲取共享數據 </h3> 7 <h3>使用mapState訪問根組件counter : {{counter}}</h3> 8 <h3>使用mapState訪問a組件counter : {{counterA}}</h3> 9 <h3>使用mapGetters訪問根組件doubleCounter : {{doubleCounter}}</h3> 10 <h3>使用mapGetters訪問a組件doubleCounter : {{doubleCounterA}}</h3> 11 <hr/> 12 <Index></Index> 13 </div> 14 </template> 15 16 <script> 17 import Index from './components/Index' 18 import { mapState,mapGetters } from 'vuex' 19 export default { 20 name: 'App', 21 components: { Index }, 22 computed: { 23 ...mapState({ 24 //訪問store根模塊 25 counter: 'counter', 26 }), 27 ...mapState('a',{ 28 //訪問a模塊 29 counterA: 'counter' 30 }), 31 ...mapGetters({ 32 //訪問store根模塊 33 doubleCounter: 'doubleCounter' 34 }), 35 ...mapGetters('a',{ 36 //訪問store根模塊 37 doubleCounterA: 'doubleCounter' 38 }) 39 40 } 41 42 } 43 </script> 44 45 <style> 46 #app { 47 font-family: 'Avenir', Helvetica, Arial, sans-serif; 48 -webkit-font-smoothing: antialiased; 49 -moz-osx-font-smoothing: grayscale; 50 text-align: center; 51 color: #2c3e50; 52 margin-top: 60px; 53 } 54 </style>
E:\MyStudy\test\VueDemo\src\components\Index.vue
1 <template> 2 <div> 3 <h1>這里是Index.vue組件</h1> 4 <h3>Index組件獲取共享數據 </h3> 5 <h3>使用mapState訪問b模塊counter :{{ counterB }}</h3> 6 <h3>使用mapGetters訪問b組件doubleCounter : {{doubleCounterB}}</h3> 7 </div> 8 </template> 9 <script> 10 import { mapState,mapGetters } from 'vuex' 11 export default { 12 name: 'Index', 13 computed: { 14 ...mapState('b',{ 15 counterB: 'counter' 16 }), 17 ...mapGetters('b',{ 18 doubleCounterB: 'doubleCounter' 19 }), 20 } 21 } 22 </script>
瀏覽器查看結果
三.總結
到此本篇文章基本已經結束了,vuex系列的三篇文章也已經結束。
關於vuex中大多數的用法基本已經覆蓋到,但是還有一些內容沒有覆蓋到。
后期攢夠一篇在繼續更新
在最后呢,再補充一點,不管是mapState和mapGetters,我們給傳入的都是一個字典。
簡單一些的,假如我們的state和getters不重名,我們可以給mapState和mapGetters傳入一個數組
1 mapState([ 2 'counterA','counterB',... 3 ]) 4 5 mapGetters([ 6 'dobuleCounterA','dobuleCounterB',... 7 ])
這樣數組中的字符串元素會直接去映射對應的state和getters。
(字典形式相當於是將state和getters中的名稱在映射過程中進行重命名)
作者:小土豆
掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d
微信公眾號:不知名寶藏程序媛(關注"不知名寶藏程序媛"免費領取前端電子書籍。文章公眾號首發,關注公眾號第一時間獲取最新文章。)
碼字不易,點贊鼓勵喲~