1. Vuex的基本使用
vuex的安装:
vuex的配置,@/store/index.js:
import {createStore} from 'vuex'//导入createStore构造函数
export default createStore({
state:{ //Vuex的状态,实际上就是存数据的地方
person:{
name:'jack',
age:200
}
},
getters:{ //提供获取Vux状态的方式, 注意在组件中调用时getPerson是以属性的方式被访问
getPerson(state){
return state.person
}
},
mutations:{ //提供直接操作Vuex的方法,注意mutations里的方法中不能有任何异步操做
ageGrow(state, value){
//第一个参数state为Vuex状态;第二个参数为commit函数传来的值
state.person.age += value
}
},
actions:{ //提供通过mutations方法来简介操作Vuex的方法
ageGrow(context, value){
//第一个参数context为上下文,提供一些方法;第二个参数为dispatch函数传来的值
context.commit('ageGrow', value)
}
},
})
在@/main.js中引入:
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app = createApp(App)
app.use(store)
app.mount('#app')
在组件中使用Vuex:
<template>
<h1>名字:{{person.name}}--年龄:{{person.age}}</h1>
<input type="text" v-model="value">
<button @click="ageGrow(value)">增加年龄</button>
<!-- 在input框输入一个数字,点击按钮,可以看到年龄发生变化,说明Vuex正常工作 -->
</template>
<script>
import {useStore} from 'vuex'
import {ref} from 'vue'
export default {
setup(){
const store = useStore() //获取store对象
let person = store.getters.getPerson //从组件中获取状态(数据)person 方式一
// let person = store.state.person //从组件中获取状态(数据)person 方式二
let value = ref('输入年龄的增量')
function ageGrow(ageGrowth){
ageGrowth = parseInt(ageGrowth)
if(isNaN(ageGrowth)){
ageGrowth = 0
}
store.dispatch('ageGrow', ageGrowth)
//通过dispatch来调用actions里的'ageGrow'方法,参数为ageGrowth
} //actions的方法又会通过commit来调用mutations里的方法,从而引起状态(数据)的变化
return {
person,
value,
ageGrow
}
}
}
</script>
<style></style>
把代码复制粘贴到脚手架中运行,可以看到直观的效果,有助于理解。
2. Module
什么叫单一状态树呢,其实就是上文中的state对象。在Vuex的基本使用中,我们使用state对象来存储Vuex的状态,state对象里面可以嵌套其他的对象,它是一个树形的结构,而且这个state对象是唯一的,所有的状态都要存储在这一个对象里。因此,我们称之为单一状态树。
这种单一状态树的弊端是显而易见的,对于中大型项目来说,要托管给Vuex的状态有很多,把这些海量的数据如果都塞到一个文件里面的一个对象里面,未免显得过于臃肿,不管是开发起来还是维护起来都会有很多不变。
对此,官方给出了解决方案:
2.1 vuex中模块化的基本使用
vuex的模块化没什么难理解的,就是把store给拆开,一个对象拆成多个对象,一个文件拆成多个文件,并且彼此可以拥有独立的命名空间。
道理很简单,所以直接看样例:
文件结构
├──src
├── components
│ └── Test.vue
└── store
├── index.js
└── modules
├── male.js
└── female.js
index.js
import {createStore} from 'vuex'
import female from './modules/female' //导入模块
import male from './modules/male' //导入模块
export default createStore({
modules:{ //使用模块
female,
male
}
})
male.js
export default {
namespaced:true, //namespaced:true代表该模块带有独立命名空间
state:{ //否则,默认是处于全局命名空间,就和非模块化一样
personList:[
{name:'张飞', id:'004'},
{name:'武则天', id:'005'},
{name:'秀吉', id:'006'},
]
},
mutations:{
addMutation(state, value){ //往personList中添加一个人
state.personList.push(value)
},
removeMutaion(state, value){ //往personList中删除一个人
state.personList = state.personList.filter((el) => el.id != value.id)
}
},
actions:{
addAction(context, value){
setTimeout(() => {
context.commit('addMutation', value) // ->'male/addMutation'
}, 1000);
},
removeAction(context, value){
context.commit('removeMutaion', value)
}
},
getters:{
personList(state){
return state.personList
}
}
}
female.js
export default {
namespaced:true, //namespaced:true代表该模块带有独立命名空间
state:{ //否则,默认是处于全局命名空间,就和非模块化一样
personList:[
{name:'李白', id:'001'},
{name:'孙尚香', id:'002'},
{name:'大乔', id:'003'},
]
},
mutations:{
addMutation(state, value){ //往personList中添加一个人
state.personList.push(value)
},
removeMutaion(state, value){ //往personList中删除一个人
state.personList = state.personList.filter((el) => el.id != value.id)
}
},
actions:{
addAction(context, value){
setTimeout(() => {
context.commit('addMutation', value) // ->'female/addMutation'
}, 1000);
},
removeAction(context, value){
context.commit('removeMutaion', value)
}
},
getters:{
personList(state){
return state.personList
}
}
}
Test.vue
<template>
<h1>女人:</h1>
<li v-for="femalePerson in femalePersons" :key="femalePerson.id">
{{femalePerson.name}}
<button @click="addToMale(femalePerson)">添加到男人</button>
</li>
<h1>男人:</h1>
<li v-for="malePerson in malePersons" :key="malePerson.id">
{{malePerson.name}}
<button @click="addToFemale(malePerson)">添加到女人</button>
</li>
<!-- 有两个列表,分布是男人和女人,通过点击按钮可以把列表中的某些项添加到另一个列表中 -->
<!-- 建议粘贴复制并运行代码,这样更直观 -->
</template>
<script>
import { computed } from '@vue/runtime-core';
import {useStore} from 'vuex'
export default {
setup(){
let store = useStore()
let malePersons = computed(() => store.getters['male/personList']) //通过getter获取state
let femalePersons = computed(() => store.state.female.personList) //直接获取state
function addToMale(person){
store.dispatch('male/addAction', person)
store.dispatch('female/removeAction', person)
//如果模块中namespaced === true,那么要在方法名前面添加模块的逻辑路径
//index.js里使用的模块为路径的起点。
//比如index里面有一个moduleA,moduleA有一个子模块moduleB,module有一个action是actionx
//那么调用方式为 store.dispatch('moduleA/moduleB/actionx', value)
}
function addToFemale(person){
store.dispatch('female/addAction', person)
store.dispatch('male/removeAction', person)
}
return {
malePersons,
femalePersons,
addToMale,
addToFemale
}
}
}
</script>
<style></style>