vuex
2023-10-01 本文已影响0人
渚清与沙白
概述
- 组件之间共享数据的方式
父向子传值:v-bind属性绑定
子向父传值:v-on属性绑定
兄弟组件之间共享数据:EventBus
- $on 接收数据的那个组件
- $emit 发送数据的那个组件
- 全局共享数据
vuex -
vuex原理
image.png
vue2使用vuex 3版本
vue3 使用vuex 4版本
import vuex from 'vuex'
Vue.use(vuex)
// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// 响应组件中的动作(异步)
const actions = {};
// 操作数据
const mutations = {};
// 存储数据
const state = {};
const getters = {};
// 创建并导出store
export default new Vuex.Store({
state,
getters,
mutations,
actions,
});
// main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
State
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state:{
count: 0
}
})
组件访问State中数据的方式
-
this.$store.state.count
在template标签中可以省略this,{{ $store.state.count }}
-
mapState
生成函数的作用 返回一个对象,key-value的value是一个函数
image.png
// 导入mapSate函数
import { mapState } from 'vuex'
// 将全局数据,映射为当前组件的计算属性
computed:{
...mapState(['count']), // 数组写法 count就是computed的一个属性
...mapState({count,'count'}), // 对象写法 key对应的count是computed对象的属性名;value对应的'count'是state对象的属性名,也是computed对象count属性的值(函数)
}
// 用法
<h1> {{ count }} </h1>
Mutation
matation用于修改state中公共数据
可以集中监控数据的变化
// 创建store数据源,提供唯一公共数据
const store = new Vuex.Store({
state:{
count: 0
},
mutations:{
add(state) {
// 变更状态
state.aount++
},
// 触发mutation时 接收参数
addNum(state,num) {
// 变更状态
state.aount += num;
}
}
})
触发mutation的第一种方式,使用commit
methods: {
handle(){
// 不传参
this.$state.commit('add');
}
handle2(){
// 传参
this.$state.commit('addNum',30);
}
}
触发mutation的第二种方式mapMutations
// 导入mapMutations函数
import { mapMutations } from 'vuex'
// 将mapMutations函数,映射为当前组件的methods方法
methods: {
...mapMutations(['add','addNum']),
handle(){
// 调用方式
this.add();
this.addNum(2);
}
}
Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
处理异步任务
触发actions异步任务时携带参数
// 定义action
const store = new Vuex.Store({
state:{
count: 0
},
mutations:{
add(state) {
// 变更状态
state.aount++
},
// 触发mutation时 接收参数
addNum(state,num) {
// 变更状态
state.aount += num;
}
},
action: {
addAsync(context, num) {
setTimeout(()=>{
context.commit('addNum',num);
},1000)
}
}
})
触发action的第一种方式dispatch
methods: {
handle() {
// 带参数
this.$store.dispatch('addAsync',5);
}
}
触发action的第二种方式mapActions
// 导入mapActions函数
import { mapActions } from 'vuex'
// 将需要的actions函数,映射为当前组件的methods方法
methods: {
...mapActions(['addAsync']),
handle() {
// 调用方式
this.$state.addAsync(this.num); // @click="addAsync(num)"
}
}
Getter
用于对State中的数据进行加工处理
形成新的数据,不会改变State中的数据
State中数据发生变化,Getter的数据也会跟着变化
// 定义getter
const store = new Vuex.Store({
state:{
count: 0
},
mutations:{
add(state) {
// 变更状态
state.aount++
},
// 触发mutation时 接收参数
addNum(state,num) {
// 变更状态
state.aount += num;
}
},
action: {
addAsync(context, num) {
setTimeout(()=>{
context.commit('addNum',num);
},1000)
}
},
getters: {
showNum: state => {
return 'getter:'+state.count;
}
}
})
使用getters第一种方式getter
this.$store.getter.showNum
template中使用可以省略this关键字
使用getters第二种方式mapGetters
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['showNum'])
},
methods: {
handle() {
this.showNum();
}
}
mapState, mapGetters, mapMutations, mapActions
的用法
<template>
<div>
<p>当前值:{{sum}}</p>
<p>当前学校:{{school}}</p>
<p>当前科目:{{subject}}</p>
<p>当前大数:{{bigSum}}</p>
<p>当前学校:{{xuexiao}}</p>"
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">+</button>
<button @click="decrementOdd(n)">-</button>
</div>
</template>
<script>
import {mapState, mapGetters, mapMutations, mapActions} from "vuex";
export default {
name: "Test",
data() {
return {
n:0,
};
},
computed: {
// 借助mapState方法生成计算属性,从state中读取数据
// 对象写法
...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
// 数组写法
...mapState(["sum",'school','subject']),
// 借助mapGetters方法生成计算属性,从getters中读取数据
// 对象写法
...mapGetters({bigSum:'bigSum'}),
// 数组写法
...mapGetters(['bigSum']),
// 模块
...mapGetters('setting', ['firstMenu', 'subMenu', 'menuData']),
},
methods:{
// mapMutations:借助mapMutations方法生成对应的方法,方法中会调用commit去联系mutations
// 对象写法
...mapMutations({increment:'JIA', decrement:'JIAN'}),
// 数组写法
...mapMutations(["JIA","JIAN"]),
// 模块account中的方法
...mapMutations("account", ["setUser", "setPermissions", "setRoles"]),
// 借助mapActions方法生成对应的方法,方法中会调用dispatch去联系actions
// 对象写法
...mapMutations({incrementOdd:'jiaOdd', decrementOdd:'jianOdd'}),
// 数组写法
...mapActions(["jiaOdd","jianOdd"]),
},
};
</script>
模块化和命名空间modules
namespaced
- 目的:更换维护,分类明确
- 优化store.js
- modules使用场景
项目复杂管理大量的状态,此时可以使用modules方式进行拆分,每一个都具有state、getter、action、matation。 - 在模块中使用:namespaced: true, 命名空间,当前模块下的标识符可以和其它模块相同,用于解决不同模块的命名冲突问题
- store目录下,创建modules文件夹,该文件夹创建index.js及拆分的模块文件。store文件夹下的index.js再导入modules ,然后进行挂载。挂栽对象格式是
{ modules: { account: {}, setting: {} } }
image.png
const countAbout = {
namespaced:true,// 开启命名空间
state: {num:1},
mutations: { ... },
actions: { ... },
getters: {
bigSum(state){
return state.num * 10;
}
}
}
const personAbout = {
namespaced:true,// 开启命名空间
state: { ... },
mutations: { ... },
actions: { ... },
}
const store = new Vuex.Store({
modules: {
countAbout,
personAbout
}
})
- 开启命名空间后,组件中读取state数据
// 方式一 自己直接读取
this.$store.state.personAbout.personList
this.$store.state.countAbout.sum
// 方式二 辅助mapState读取
...mapState('countAbout',['sum','shcool','subject'])
- 开启命名空间后,组件中读取getters数据
// 方式一 自己直接读取
this.$store.getters['personAbout/firstName']
// 方式二 辅助mapGetters读取
...mapGetters('countAbout',['bigSum'])
- 开启命名空间后,组件中调用dispatch
// 方式一 自己直调用dispatch
this.$store.dispatch('personAbou/addPersonWang',personObj)
// 方式二 辅助mapActions
...mapActions('countAbout',{incrementOdd:'jiaOdd'})
- 开启命名空间后,组件中调用commit
// 方式一 自己直接调用commit
this.$store.commit('personAbout/ADD_PERSON',personObj)
// 方式二 辅助mapMutations
...mapMutations('countAbout',{increment:'JIA'})