1.vuex是什么
- 概念:专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
- Github地址:https://github.com/vuejs/vuex
2.什么时候适用vuex
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
简单来说就是组件A、B、C、D使用共同的属性{x:1},任意一个组件修改x属性时都会使其他组件中使用的x属性发生改变
vuex工作原理图
3.搭建vuex环境
1. 下载vuex
npm i vuex
2.创建文件: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
})
3.在main,js中创建vue实例时传入store配置项
......
//引入store
import store from './store'
......
new Vue({
el: '#app',
store,
render: h => h(App),
});
4.基本使用
1.初始化数据、配置actions、配置mutations,操作store.js
在src/store/index.js中
//引入vue核心库
import Vue from 'vue'
//引入vuex
import vuex from 'vuex'
//应用vuex插件
Vue.use(vuex);
//响应组件中用户的动作
const actions: {
jia(context,value){
//context 相当于简略版的Store
//value 组件传过来的值
context.commit("JIA",value) //JIA最好有大写 方便区分函数
}
jian(context,value){
context.commit('JIAN',value)
},
jiaOdd(context,value){
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//修改state中的数据
const mutations: {
JIA(state,value){
state.sum += value
}
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//保存具体的数据
const state: {
sum:0
}
//创建并暴露 store
export default new.Vuex.Store({
actions,
mutations,
state
})
2.组件中读取vuex中的数据: (this.)$store.state.sum
3.组件中修改vuex中的数据: (this.)$store.dispatch('actions中方法名',数据) 或 (this.)$store.commit('mutations中方法名',数据)
备注:若没有网路请求或其他业务逻辑可以越过actions,即不写dispatch直接编写commit
5.getters的使用
1.在src/store/index.js加入getters
......
//准备getters对象--用与将state中的数据进行加工
const getters: {
bigSum(state){
return state.sum*10 // 将state中的sum*10
}
}
......
//创建并暴露 store
export default new.Vuex.Store({
......,
getters
})
2.组件中读取vuex中的数据:(this.)$store.getters.sum
备注:对state中的数据进行加工,但不会影响其的值。相当于vue中的computed计算属性
6.四个map的方法的使用
因为vue中的插值表达式{{}},只能写一些简单的逻辑,所以需要尽可能的简化一下
例如:{{$store.state.sum}} 最好简化成 {{sum}},可以借助计算属性computed
原生写法
computed:{
sum(){ //方法名建议与$store.state的属性名保持一致
return this.$store.state.sum
},
//但如果需要用的属性比较多的话,则需要这样
name1(){
return this.$store.state.name1
},
name2(){
return this.$store.state.name1
},
......
},
methods: {
JIA(){this.$store.commit('JIA',this.n)},
JIAN(){this.$store.commit('JIAN',this.n)},
jiaOdd(){this.$store.dispatch('jiaOdd',this.n)},
jiaWait(){this.$store.dispatch('jiaWait',this.n)},
}
借助vuex写法
在使用下列方法前,先按需引入对应的方法 import { mapState,mapGetters,mapActions,mapMutations } from 'vuex'
1.mapState方法:
用于帮助我们映射state中的数据为计算属性
computed:{
//对象写法
...mapState({sum:'sum1',name1:'name1',name2:'name2'}) //键与值可以不一样 sum==计算属性 'sum'是state中的属性 //所以$store.state中必须要有此属性
//数组写法
...mapState(['sum1','name1','name2']) //相当于对象的键与值都是字符串,
//...mapState(['sum1','name1','name2']) ==》 ...mapState({sum:'sum1',name1:'name1',name2:'name2'})
// 函数写法
...mapState({
sum: state=>state.sum,
mmd: state=>state.name1 // mmd =》本组件中想使用的属性名
//...
})
}
2.mapGetters方法:
computed:{
//对象写法
...mapState({bigSum:'bigSum'})
//数组写法
...mapState(['bigSum'])
}
3.mapActions方法
methods:{
// 对象写法
...mapActions({jiaOdd:'jiaOdd',jiaWait:'jiaWait'})
// 数组写法
...mapActions(['jiaOdd','jiaWait'])
}
4.mapMutations方法
methods:{
// 对象写法
...mapMutations({JIA:'JIA',JIAN:'JIAN'}),
// 对象写法
...mapMutations(['JIA','JIAN']),
}
注意:
1.因为mapState({sum:'sum1'})中键与值都是字符串,所以不能使用简写{sum}
2.mapActions 与 mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象
7.模块化+命名空间
1.目的:让代码更好维护,让多种数据分类更加明确
2.修改store.js
为了解决不同模块命名冲突的问题,将不同模块的namespaced: true(默认false),之后在不同页面中引入getteractions mutations 时,需要加上所属的模块名
const countAbout = {
namespaced: true, // 开启命名空间
state: {x:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){ return state.sum * 10 }
}
}
const personAbout = {
namespaced: true, // 开启命名空间
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
countAbout, // ==> countAbout:countAbout
personAbout
}
})
3.开启命名空间后,组件中读取state数据
// 方式一:自己直接读取
this.$store.state.personAbout.list
// 方式二:借助mapState读取:
...mapState('countAbout',['sum','name1','name2']), //第一个值:模块名(前提要开启命名空间), 第二个值:该模块中state有的属性
4.开启命名空间后,组件中读取getters 数据
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
5.开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{Add:'jiaOdd',jiaWait:'jiaWait'}) //Add:当前组件中的方法名 jiaOdd jiaOdd:vuex中的actions里的方法名
// ...mapActions('countAbout',['jiaOdd','jiaWait']) //数组写法
6.开启命名空间后,组件中调用commit
//方式一:自己直接commit
this.$store.commit('personAbout/JIA',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{JIA:'JIA',JIAN:'JIAN'}),
备注:
在实际开发中使用模块化开发时,最好单独为countAbout, personAbout创建文件夹
1.src/ store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import countOptions from './count' // 引入count
import personOptions from './person' // 引入person
Vue.use(Vuex)
//创建并暴露store
export default new Vuex.Store({
modules:{
countOptions,
personAbout,
}
})
2.src/ store / count.js
export default {
namespaced:true,
actions: {
addOdd(context,value){
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
addWait(context,value){
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
},
mutations: {
JIA(state,value){ state.sum += value },
JIAN(state,value){ state.sum -= value }
},
state: {
sum:0,
},
getters: {
bigSum(state){ return state.sum * 10 }
}
}
3.src/ store/ person.js
import axios from "axios"
import { nanoid } from "nanoid"
export default{
namespaced:true,
actions:{},
mutations:{
JIA(state,value){
state.personList.unshift(value)
}
},
state:{
personList:[]
},
getters:{
firstPersonName(state){ return state.personList[0].name }
}
}
vuex中五大属性总结:
- state 保存具体的数据
- getters 对state中的数据进行加工,但不影响state中的数据
- mutations 修改state中的数据
- actions 响应组件中用户的动作(网路请求或业务逻辑)
- modules 模块化,对数据进行分类管理