作者:小土豆
微信公众号:不知名宝藏程序媛(关注第一时间获取最新文章)
码字不易,点赞鼓励哟~
前言
本文章是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
使用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
的源码才能知晓,因此这里不在探究。
使用mapGetters
前面使用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]-Vuex入门实践(下)
写在最后
如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者
文章公众号
首发,关注 不知名宝藏程序媛
第一时间获取最新的文章
笔芯❤️~