欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > Vue(十二) Vuex、四个map方法的使用、Vuex模块化+namespace命名空间

Vue(十二) Vuex、四个map方法的使用、Vuex模块化+namespace命名空间

2025/2/25 4:34:20 来源:https://blog.csdn.net/qq_44285582/article/details/141281379  浏览:    关键词:Vue(十二) Vuex、四个map方法的使用、Vuex模块化+namespace命名空间

文章目录

  • 一、Vuex
    • 前言:求和案例
    • 1. 搭建Vuex环境
    • 2. 基本使用
    • 3. 常见疑惑
    • 4. getters
    • 5. 四个map方法的使用
      • (1) mapState
      • (2) mapGetters
      • (3) mapActions
      • (4) mapMutations
    • 6. 模块化+命名空间namespace
      • 6.1 模块化
      • 6.2 模块化后读取数据

一、Vuex

Vuex是一个Vue插件,用来实现集中式状态(数据)管理。简单来说就是,当多个组件需要读写同一数据时。使用vuex来管理这个数据,会更方便多个组件读写。
在这里插入图片描述
原理图:
在这里插入图片描述

前言:求和案例

接下来都是结合这个求和案例来说明vuex的使用
在这里插入图片描述
Count组件的点击事件分别为:

  <button @click="increment">+</button><button @click="decrement">-</button><button @click="incrementOdd">当前和为奇数再加</button><button @click="incrementWait">等一等再加</button>

对应的监听事件为:

// data中存有sum和n两个属性;sum是求和结果,n是用户在下拉框中选择的数字increment () {this.sum = this.sum + this.n},decrement () {this.sum = this.sum - this.n},incrementOdd () {if (this.sum % 2 != 0) {this.sum = this.sum + this.n}},incrementWait () {setTimeout(() => {this.sum = this.sum + this.n}, 1000)}

1. 搭建Vuex环境

1.安装vuex

  • vue2只能使用vuex3版本:npm i vuex@3
  • vue3只能使用vuex4版本:npm i vuex@4

2.导入并使用vuex

	import Vuex from 'vuex'Vue.use(Vuex)

有这两句代码之后,vue实例里就可以写store配置项。写了store配置项,所有的vc和vm都能够接触到$store

3.创建store文件:src/store/index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}//创建并暴露store实例
export default new Vuex.Store({actions,mutations,state
})
  1. main.js中创建vm时传入store配置项
//引入storeimport store from './store'//创建vmnew Vue({el:'#app',render: h => h(App),store})

问:为什么要在store/index.js文件里执行Vue.use(Vuex),而不是在main.js文件:

答:因为规定创建store实例之前,必须执行Vue.use(Vuex)这条语句。vue在解析main.js时,首先将所有import的文件先走一遍,再执行其他语句。因此,即使Vue.use(Vuex)写在第三行的import store from './store'之前,也是先进入store文件,创建store实例,然后再执行Vue.use(Vuex)。所以干脆在store/index.js里引入。

2. 基本使用

1.初始化数据、配置actions、配置mutations,操作store文件index.js

// index.js,方法简单写了几个,没全写
...
// 初始化数据——state用于存储数据
const state = {sum: 0
}// 准备actions——用于响应组件中的动作
const actions = {add (context, value) {// 这里未进行任何逻辑处理,所以组件可直接调用commit,而不是调用dispatch先进入到actionscontext.commit('ADD', value)},addWait (context, value) {setTimeout(() => {context.commit('ADD', value)}, 1000)}
}
// 准备mutations——用于操作数据(state)
const mutations = {ADD (state, value) {state.sum += value}
}

2.组件中修改vuex中的数据

// Count.vue里监听事件
increment () {this.$store.dispatch('add', this.n)
},

3.组件中读取vuex中的数据:

<!--(插值表达式中不需要写this)--><h1>当前求和为{{ $store.state.sum }}</h1>

4.如果没有其他逻辑,组件也可以越过actions直接给mutations发送消息

// Count.vue里监听事件
increment () {this.$store.commit('ADD', this.n)
},

5.逻辑操作一般都写在actions里面

3. 常见疑惑

  • 问: action里的函数参数为(context,value),为什么不直接给commit,还要给一个context
    答: 上下文context里包含这些内容
    在这里插入图片描述
    先只看熟悉的这几个。
    state:actions在进行业务逻辑处理时,有可能会用到state里的数据进行处理。
    dispatch:actions里,若某一个操作包含很多业务逻辑,则可能会处理完一部分后,dispatch给actions里的另一个函数继续进行逻辑处理。
    所以,只包含commit不够周到

  • 问: 业务逻辑为什么要写在actions里边,直接写在组件的点击事件里边不行吗
    答: 当业务逻辑十分复杂(比如核实发票信息之类的)时,逻辑写在actions里,其他人需要核实发票信息时直接用这套逻辑就好了。如果写在点击事件里,每个人都写一遍这套逻辑,代码冗余量提升。所以写在actions里可以减少代码冗余。

4. getters

1.概念 :当state中的数据需要经过加工后再使用时,可以使用getters加工。(有点类似于组件中的computed)

2.在storge文件中添加配置

...
const getters = {bigSum (state) {return state.sum * 10}
}
...
export default new Vuex.Store({...getters
})

3.组件中读取getters里的数据 $store.getters.bigSum

5. 四个map方法的使用

假设在store/index.js中:

// 准备state——用于存储数据
const state = {sum: 0,// 新增两个属性name: 'tom',age: 10
}

(1) mapState

借助mapState生成成计算属性(computed中生成),从state中读取数据

import { mapState} from 'vuex'
computed: {
//原始获取state数据的方法
mingzi () {return this.$store.state.name
},
nianling () {return this.$store.state.age
},
// mapState对象写法。(生成计算属性的名称为he,值是state里的sum属性中读取的数据)...mapState({ he: 'sum', mingzi: 'name', nianling: 'age' }),
// mapState数组写法,生成的计算属性:sum、name、age
...mapState(['sum', 'name', 'age']),  
}
// Count.vue组件
// 应用mapState对象写法生成的计算属性
<h3>学生姓名为:{{ mingzi }},年龄为:{{ nianling }}</h3>
// 数组写法
<h3>学生姓名为:{{ name }},年龄为:{{ age }}</h3>

在这里插入图片描述

(2) mapGetters

借助mapGetters生成计算属性,从getters中读取数据

import { mapGetters } from 'vuex'
//原始写法:bigSum () {return this.$store.getters.bigSum},
// 数组写法
...mapGetters(['bigSum']),
// 对象写法
...mapGetters({ bigSum: 'bigSum' })

(3) mapActions

借助mapActions生成对应的方法,方法中会调用dispatch去联系actions

import { mapActions } from 'vuex'
// 原始方法
incrementWait () {this.$store.dispatch('addWait', this.n)
}// 对象写法
...mapActions({ incrementOdd: 'addOdd', incrementWait: 'addWait' }),
// 数组写法
...mapActions(['addOdd', 'addWait']),

采用map形式时,组件中调用方法:

//mapActions采用对象写法,注意此处传参
<button @click="incrementOdd(n)">当前和为奇数再加</button>
//mapActions采用数组写法
<button @click="addOdd(n)">当前和为奇数再加</button>

(4) mapMutations

借助mapMutations生成对应的方法,方法中会调用commit去联系mutations

import { mapMutations, } from 'vuex'
// 原始写法
decrement () {this.$store.commit('MINUS', this.n)
},
// 对象写法
...mapMutations({ increment: 'ADD', decrement: 'MINUS' }),
// 数组写法
...mapMutations(['ADD','MINUS']),

总结

  1. mapState和mapGetters优化了计算属性;mapMutations和mapActions优化了方法。

  2. map方法采用对象写法{key:value}时:key为组件中使用该属性/方法时的名称,value为vuex里对应的属性名/方法名

  3. 采用数组写法时:组件中该属性名/方法名与vuex里的属性名/方法名一致

注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数默认是事件对象。

6. 模块化+命名空间namespace

根据功能,将相关的配置分类,让代码更好维护,让多种数据分类更加明确。

6.1 模块化

比如现在有Count和Dog两个vue组件。两个组件都往vuex中存放了一些数据。修改文件

// store.js
const countOptions ={namespaced: true, // 开启命名空间actions: {...},mutations: { ...},state: {...},getters: {...}
},
const dogOptions ={namespaced: true, // 开启命名空间actions: {...},mutations: { ...},state: {...},getters: {...}
},
export default new Vuex.Store({modules: {countAbout: countOptions,dogAbout: dogOptions// keyvalue名称一致时,也可以用简写形式// countOptions,// dogOptions}

或者将countOptions与dogOptions分别放入两个js文件

// count.js
export default {namespaced: true, // 开启命名空间actions: {...},mutations: { ...},state: {...},getters: {...}
}
// dog.js
import axios from 'axios'
import { nanoid } from 'nanoid'         
export default {namespaced: true, // 开启命名空间actions: {addDogServe (context) {//Actions部分向外发送请求axios.get('https://api.xygeng.cn/one').then(response => {context.commit('AddDogs', { id: nanoid(), name: response.data.data.tag })},error => {alert(error.message)})}},mutations: { ...},state: {...},getters: {...}
}
// store.js
import countOptions from './count'
import dogOptions from './dog'
export default new Vuex.Store({
modules: {countAbout: countOptions,dogAbout: dogOptions
}

6.2 模块化后读取数据

由于将数据分类到不同的模块里,因此需要给模块开启命名空间namespace,才能确保读取到该模块的数据。

1、采用map方法读取数据,调用方法

// mapState方式读取不同模块的数据
...mapState('countAbout', { he: 'sum', mingzi: 'name', nianling: 'age', dogs: 'dogs' }),
...mapState('dogAbout', ['dogs']),// mapGetters方式读取不同模块的数据
...mapGetters('countAbout', ['bigSum']),// mapActions方式
...mapActions('countAbout', { incrementOdd: 'addOdd', incrementWait: 'addWait' }),
// mapMutations方式    ...mapMutations('countAbout', { increment: 'ADD', decrement: 'MINUS' }),

2、不采用map方法,自己读取state、getters数据,调用commit、dispatch方法

computed(){dogs () {return this.$store.state.dogAbout.dogs},firstDog(){return this.$store.getters['dogAbout/getFirstDog']}
},
methods(){addDog () {this.$store.commit('dogAbout/AddDogs', { id: nanoid(), name: this.dogName })},addDogRandom () {this.$store.dispatch('dogAbout/addDogServe')}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词