作者:小土豆biubiubiu
简书:www.jianshu.com/u/cb1c3884e…
微信公众号:土豆妈的碎碎念(扫码关注,一起吸猫,一起听故事,一起学习前端技术)
码字不易,点赞鼓励哟~
本文章是Vuex
系列的最后一篇,主要总结的是如何使用mapState
和mapGetters
访问Vuex
中的state
和getters
。
上一篇文章 [手把手式教程,适合新手入门Vuex]-Vuex入门实践(中) 里面我们总结的是多模块的内容,所以关于store.js
、moduleA.js
和moduleB.js
的代码保持不变。
在此为了方便观看,我将这三个文件的代码在贴在这里。
// E:\MyStudy\test\VueDemo\src\vuex\store.js import Vue from 'vue' import Vuex from 'vuex' import moduleA from './moduleA' import moduleB from './moduleB' Vue.use(Vuex) export default new Vuex.Store({ state: { counter: 1000 }, mutations: { //递增 increase(state) { console.log("store-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 } }, modules: { a: moduleA, b: moduleB } }) 复制代码
// 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 const moduleB = { namespaced: true, state:{ counter: 5 }, mutations: { //递增 increase(state) { console.log("moduleB-increase") state.counter++ }, //递减 decrementAction(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 moduleB 复制代码
注意这里不能缺少
命令空间
的配置哦
现在需要在组件中使用mapState
、mapGetters
对state
和getters
进行访问,还是按照之前的套路:
在App.vue组件中访问store根模块、a模块的state和getters 在Index.vue组件中访问b模块的state和getters 复制代码
使用mapState
访问state
的写法也有多种,我们一个一个来实践。
我们先直接上代码。
<!-- 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> 复制代码
在组件中使用mapState
,首先第一步
需要引入mapState
。
import { mapState } from 'vuex' 复制代码
接着就是在组件的计算属性computed
使用mapState
,以Index
组件中的代码为例。
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
。
第二种写法和第一种有些类似,只是以字符串
的形式返回计算属性。
我们先在Index.vue
组件中访问b
模块的数据。
<!-- 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('b',{ counterB: 'counter' }) } </script> 复制代码
核心代码如下:
computed: mapState('b',{ counterB: 'counter' }) 复制代码
可以看到,这种写法mapState
第一个参数限定了模块名称
。接着就是以counter
字符串的形式返回了b
模块的counter
值。那么我们就可以知道访问store
跟模块、a
模块的方法如下:
访问根模块的数据,不需要限定第一个参数 访问a模块的数据,需要限定第一个参数为a 复制代码
接着就有个问题了:访问store
根模块、a
模块的state
代码同在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混合使用
。
混合使用这个点日常开发会用到,很实用的一个点
最后我们在使用浏览器查看一下最终App.vue
和Index.vue
中的结果。
注意:
这种关于
mapState
的写法不能删除moduleA
和moduleB
中关于命令空间的配置,否则会报错。最后作者还尝试了一个问题,就是将
moduleA.js
中的state
属性改为counterA
。然后修改了
最后发现这样并不能正常访问到App.vue
组件中computed
访问a
模块数据的代码a
模块的state
数据(删除a
模块的命名空间配置也无法正常访问)这个尝试仅给大家一个反面的示例,具体为什么不能访问应该需要去阅读
Vuex
的源码才能知晓,因此这里不在探究。
前面使用mapState
访问了state
数据,那么现在我们使用mapGetters
访问一下Vuex
中的getters
。
在尝试之后发现,暂时发现使用
mapGetters
访问Vuex
中的getters
只有字符串的形式
<!-- 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> <h3>使用mapGetters访问根组件doubleCounter : {{doubleCounter}}</h3> <h3>使用mapGetters访问a组件doubleCounter : {{doubleCounterA}}</h3> <hr/> <Index></Index> </div> </template> <script> import Index from './components/Index' import { mapState,mapGetters } from 'vuex' export default { name: 'App', components: { Index }, computed: { ...mapState({ //访问store根模块 counter: 'counter', }), ...mapState('a',{ //访问a模块 counterA: 'counter' }), ...mapGetters({ //访问store根模块 doubleCounter: 'doubleCounter' }), ...mapGetters('a',{ //访问store根模块 doubleCounterA: 'doubleCounter' }) } } </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> <h3>使用mapGetters访问b组件doubleCounter : {{doubleCounterB}}</h3> </div> </template> <script> import { mapState,mapGetters } from 'vuex' export default { name: 'Index', computed: { ...mapState('b',{ counterB: 'counter' }), ...mapGetters('b',{ doubleCounterB: 'doubleCounter' }), } } </script> 复制代码
App组件中关于mapGetters
的核心代码如下:
computed: { ...mapGetters({ //访问store根模块 doubleCounter: 'doubleCounter' }), ...mapGetters('a',{ //访问store根模块 doubleCounterA: 'doubleCounter' }) } 复制代码
Index组件中关于mapGetters
的核心代码如下:
computed: { ...mapGetters('b',{ doubleCounterB: 'doubleCounter' }), } 复制代码
浏览器查看结果:
到此本篇文章基本已经结束了。
在最后呢,再补充一点,不管是mapState
和mapGetters
,我们给传入的都是一个字典。
...mapState({ counter: 'counter', }), ...mapGetters({ doubleCounter: 'doubleCounter' }), 复制代码
简单一些的,假如我们的state
和getters
不重名,我们可以给mapState
和mapGetters
传入一个数组。
mapState([ 'counterA','counterB',... ]) mapGetters([ 'dobuleCounterA','dobuleCounterB',... ]) 复制代码
这样数组中的字符串元素会直接去映射对应的state
和getters
。
字典形式相当于是将
state
和getters
中的名称在映射过程中进行重命名
到此[手把手式教程,适合新手入门Vuex]-Vuex入门实践
这整个系列就结束了,都是一些关于Vuex
基础的用法,比较适合新手刚开始学习和实践Vuex
。
最后呢,将这个系列的所有文章链接整理到这里,方便大家观看。
[手把手式教程,适合新手入门Vuex]-Vuex入门实践(上)
[手把手式教程,适合新手入门Vuex]-Vuex入门实践(中)
[手把手式教程,适合新手入门Vuex]-Vuex入门实践(下)
小土豆biubiubiu
一个努力学习的前端小菜鸟,知识是无限的。坚信只要不停下学习的脚步,总能到达自己期望的地方
同时还是一个喜欢小猫咪的人,家里有一只美短小母猫,名叫土豆
土豆妈的碎碎念
微信公众号的初衷是记录自己和身边的一些故事,同时会不定期更新一些技术文章
欢迎大家扫码关注,一起吸猫,一起听故事,一起学习前端技术
欢迎大家扫描微信二维码进入群聊讨论问题(若二维码失效可添加微信JEmbrace拉你进群)
小小总结,欢迎大家指导~