这是我参与「第四届青训营 」笔记创作活动的第15天
今天来复习一下Vuex的使用
- 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中的多个组件的共享状态进行集中式的管理(读/写),也是一种组件金童新的方式,且适用于任意组件间通信。
- 何时使用:多个组件需要共享数据时
(1)搭建vuex环境
1.创建文件: 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
})
2.在main.js 中创建vm时传入store配置项
// 引入store
import store from './store'
//创建vm
new Vue({
el:'#app',
render:h =>h(app),
store
})
使用方法:
在组件中调用dispatch()或直接commit()
increase () {
this.$store.commit('INCREASE',this.n)
},
decrease () {
this.$store.commit('DECREASE',this.n)
},
odd_increase () {
this.$store.dispatch('odd_increase',this.n)
},
wait_increase () {
setTimeout(()=>{
this.$store.dispatch('wait_increase',this.n)
},2000)
}
}
在store文件夹下index.js中的actions书写逻辑,mutation进行数据变换,state中写入原始数据
注意: 组件中修改数据:this.store.commit('mutations中的方法名',数据)。若没有网络请求或业务逻辑,组件也可以越过actions,即不写dispatch(),直接commit()。
const actions={
odd_increase(context, value) {
if (state.sum % 2) {
context.commit('ODD_INCREASE',value) }
},
wait_increase(context, value) {
context.commit('WAIT_INCREASE',value)
}
}
-----------------------------------------------------------------------
const mutations={
INCREASE(state, value) {
state.sum+=value
},
DECREASE(state, value) {
state.sum-=value
},
ODD_INCREASE(state, value) {
state.sum+=value
},
WAIT_INCREASE(state, value) {
state.sum+=value
}
}
---------------------------------------------------------------------------
const state={
sum:0
}
在组建中使用Vuex中存储的数据
<h1>当前的值为:{{$store.state.sum}}</h1>
注意组件模板中可以直接使用store.state.sum
(2)getters的使用
-
1.概念:当state中的数据需要加工后再使用,可以使用getters
-
2.在index.js中追加配置getters
const getters={ bigSum(state){ return state.sum*10 } } ---------------------- export default new Vuex.Store({ actions, mutations, state, getters } -
3.组件中读取数据:$store.getters.bigSum
(3)四个map方法的使用
使用这些方法前需要导入:import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
用那个导入那个
-
mapState()方法:用于帮助我们映射state中的数据为计算属性
computed:{ // 借助mapState生成计算属性:sum,school,subject (对象写法) ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}) // 借助mapState生成计算属性:sum,school,subject (数组写法) ...mapState(['sum','subject','school']) } -
mapGetters方法:用于帮助我们映射getters中的数据为计算属性
computed:{
// 借助mapGetters生成计算属性:sum,school,subject (对象写法)
...mapGetters({bigSum:'bigSum'})
// 借助mapGetters生成计算属性:sum,school,subject (数组写法)
...mapGetters(['bigSum'])
}
- mapActions方法:用于帮助我们生成与actions对话的方法,即包含$store.dispatch(xxx)的函数
methods:{
// 借助mapActions生成odd_increase,wait_increase(对象写法)
...mapActions({odd_increase:'odd_increase',wait_increase:'wait_increase'})
// 借助mapActions生成odd_increase,wait_increase(数组写法)
...mapActions(['odd_increase','wait_increase'])
}
当mapActions,mapMutations使用时,若需要传递参数:要在模板绑定事件的回调函数中传递好参数,否则会将默认的event事件对象当成参数传递,引起错误。
<button @click="odd_increase(n)">当前和为奇数才加</button>
- mapMutations方法:用于帮助我们生成与mutations对话的方法,即包含$store.commit(xxx)的函数
methods:{
// 借助mapMutations生成INCREASE,DECREASE(对象写法)
...mapMutations({INCREASE:'INCREASE',DECREASE:'DECREASE'})
// 借助mapMutations生成INCREASE,DECREASE(数组写法)
...mapMutations(['INCREASE','DECREASE'])
}
注意当这些方法需要传递参数时,应在调用生成的方法是进行手动传参:
<button @click="INCREASE(n)">+</button>
<button @click="DECREASE(n)">-</button>
谨记:数组写方法中的名字有两个作用 ------
1.作为包含$store.commit的函数方法名
2.作为store文件夹下index.js文件中mutations中对应的方法名
(4)vuex的模块化开发
多个组件的actions,mutations,state,getters在一起,代码冗余在一起,不利于维护
将上方例子模块化:
- 将Count,Person组件的actions,mutations等写在不同的对象或文件中
const CountOptions = {
namespaced:true,
actions : {
//准备actions——用于响应组件中的动作
odd_increase(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('INCREASE',value)
}
},
wait_increase(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('INCREASE',value)
},500)
}
},
//准备mutations——用于操作数据(state)
mutations: {
INCREASE(state, value) {
console.log('mutations中的JIA被调用了')
state.sum += value
},
DECREASE(state, value) {
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
},
//准备state——用于存储数据
state : {
sum:0, //当前的和
school:'尚硅谷',
subject:'前端',
},
//准备getters——用于将state中的数据进行加工
getters : {
bigSum(state){
return state.sum*10
}
}
}
--------------------------------------------------------------------------------------------------------
const PersonOptions = {
namespaced:true,
actions: {
// 添加姓王的人名
add_wang(context, value) {
if (value.name.indexOf('王') === 0) {
context.commit('ADD_PERSON',value)
} else {
alert('人名必须姓王')
}
},
randomadd(context) {
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response => {
context.commit('ADD_PERSONSERVER', {id:nanoid(),name: response.data })
},
error => {
alert(error.message)
}
)
}
},
mutations: {
ADD_PERSON(state, value) {
console.log('mutations中的ADD_PERSON被调用了')
state.personList.unshift(value)
},
ADD_PERSONSERVER(state,value) {
state.personList.push(value)
}
},
state: {
personList:[
{id:'001',name:'张三'}
]
},
getters: {
fristListName(state) {
return state.personList[0].name
}
}
}
- 声明空间namespaced和导出时模块化
建立组件对象时加上namespaced:true
导出时利用modules{}
//创建并暴露store
export default new Vuex.Store({
modules: {
Countabout: CountOptions,
Personabout: PersonOptions
},
})
- 使用state数据,调用action,mutations,getters方法的方式
使用map方法简写时: ...mapxxx('模块组件名',['属性'])
computed:{
...mapState('Countabout',{he:'sum',xuexiao:'school',xueke:'subject'}) //(对象写法)
...mapState('Countabout',['sum','school','subject']), // (数组写法)
...mapState('Personabout',['personList']),
...mapGetters('Countabout',['bigSum'])
},
methods:{
...mapActions('Countabout',['odd_increase','wait_increase']),
...mapMutations('Countabout',['INCREASE','DECREASE'])
}
直接this.$store.xxx时:this.$store.xxx('模块组件名/方法名',‘数据’) this.$store.xxx.模块组件名.属性
this.$store.dispatch('Personabout/k',personObj)
this.$store.commit('Personabout/ADD_PERSON',personObj)
computed:{
personList(){
return this.$store.state.Personabout.personList
},
sum(){
return this.$store.state.Countabout.sum
},
fristListName(){
return this.$store.getters['Personabout/fristListName'] //要使用对象的第二种取属性方法 obj['属性名']
}
},