概念
Vuex:状态管理工具
使用场景
有时候,需要在多个组件中共享状态,并且是响应式的状态,一个变,全都跟着发生改变的场景。
例如,一些全局要用的的状态信息:用户登录状态、用户信息等等;
这时候,就需要这样的一个工具来进行全局的状态管理,而 Vuex 就是这样的一个工具。
Vue2.x vuex
基本结构
store/index.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state:{},
actions:{},
mutaions:{},
modules:{},
getters:{}
)}
Vue3 vuex
基本结构
Vue3 里面基本上都是工厂函数,从 vue 变成 createApp , store 也封装成为了一个函数:createStore ,如下所示:
src/store/index.ts:
import { createStore } from 'vuex'
export default createStore({
state: {
},
mutations: {
},
actions: {
},
getters: {
},
modules: {
}
})
state 类似于 vue 中的 data ,用于存放数据模型;
getters 类似于 vue 中 computed ,相当于 state 的计算属性;
mutations 类似于 vue 中的 method ,只有通过它的方法函数可以改变 state 的值,而且,它的方法函数必须是同步,不能是异步;
actions :只能通过它来调用 mutations 来改变 state 的值,它的函数方法可以是异步的;
modules :可以引入多个 module ,通过这个属性,可以添加多个 module 进入 Vuex 的 store 中。
使用
src/main.ts:
import { createApp } from 'vue'
import Antd from 'ant-design-vue'
import router from './router/index'
import store from './store'
import App from './App.vue'
import 'ant-design-vue/dist/antd.css'
const app = createApp(App)
app.use(Antd)
app.use(store)
app.use(router)
app.mount('#app')
src/store/index.ts:
import { createStore } from 'vuex'
export default createStore({
state: {
count: 1
},
mutations: {
updateCount(state,newVal){
state.count = newVal
}
},
actions: {
setCount(context,newVal){
context.commit('updateCount',newVal)
}
},
getters: {
getCount(state){
return state.count
}
},
modules: {
}
})
src/views/TestPage.vue:
<template>
<div>
<h1>vuex数据-state、getters:{{$store.getters.getCount}}</h1>
<h1>count:{{count}}</h1>
<a-button @click="clickHandle">点击修改</a-button>
</div>
</template>
<script>
import { useStore } from 'vuex'
import { computed } from "vue";
export default {
name: 'test',
setup () {
const store = useStore()
let count = computed(() => { return store.state.count });
const clickHandle = () => {
store.dispatch('setCount', 3)
}
return {
count,
clickHandle
}
}
};
</script>
页面展示: 
点击按钮: 
模块化
store/index.ts:
import { createStore } from 'vuex'
import count from './modules/count'
import user from './modules/user'
export default createStore({
modules:{
user,
count
},
})
store/modules/count.ts:
const count = {
state: {
count: 1
},
mutations: {
updateCount(state:object|any,payload:number){
state.count = payload
}
},
actions: {
setCount(context,payload){
context.commit('updateCount',payload)
}
},
getters: {
getCount:state=> state.count
},
}
export default count
store/modules/user.ts:
const initPersonState = () => {
return {
personInfo: {
id: "12",
name: "小明",
age: 18
}
};
};
const user = {
state: initPersonState(),
mutations: {
updateUserInfo(state:object|any,payload:string){
state.personInfo.name = payload
}
},
actions: {
setUserInfo(context,payload){
context.commit('updateUserInfo',payload)
}
},
getters: {
getUserInfo(state){
return 'Hello, ' + state.personInfo.name
}
}
};
export default user;
组件内使用:
<template>
<div>
<h1>vuex数据-state count、getters:{{$store.getters.getCount}}</h1>
<h1>vuex数据-state user、getters:{{$store.getters.getUserInfo}}</h1>
<h1>count:{{count}}</h1>
<a-button @click="clickHandle">点击修改count</a-button>
<a-button @click="changeHandle">点击修改用户信息</a-button>
</div>
</template>
<script>
import { useStore } from 'vuex'
import { computed } from "vue";
export default {
name: 'test',
setup () {
const store = useStore()
let count = computed(() => { return store.state.count });
const clickHandle = () => {
store.dispatch('setCount', 3)
}
const changeHandle = () => {
store.dispatch('setUserInfo', 'xiaofang')
}
return {
count,
clickHandle,
changeHandle
}
}
};
</script>
页面效果: 
点击按钮修改count: 
点击按钮修改用户信息: 
命名空间
带命名空间 namespaced: true 的模块,所有功能区分模块,更高封装度和复用。
修改store/modules/user.ts:
const initPersonState = () => {
return {
personInfo: {
id: "12",
name: "小明",
age: 18
}
};
};
const user = {
namespaced: true,
state: initPersonState(),
mutations: {
updateUserInfo(state:object|any,payload:string){
state.personInfo.name = payload
}
},
actions: {
setUserInfo(context,payload){
context.commit('updateUserInfo',payload)
}
},
getters: {
getUserInfo(state){
return 'Hello, ' + state.personInfo.name
}
}
};
export default user;
和前面例子区别在于: 
带命名空间组件内的使用与之前不同:
<template>
<div>
<!-- 不带命名空间 -->
<h1>vuex数据-state count、getters:{{$store.getters.getCount}}</h1>
<h1>vuex数据-state user、getters:{{$store.getters.getUserInfo}}</h1>
<!-- 带命名空间 -->
<h1>vuex数据-state count、getters:{{$store.getters['count/getCount']}}</h1>
<h1>vuex数据-state user、getters:{{$store.getters['user/getUserInfo']}}</h1>
<h1>count:{{count}}</h1>
<a-button @click="clickHandle">点击修改count</a-button>
<a-button @click="changeHandle">点击修改用户信息</a-button>
</div>
</template>
<script>
import { useStore } from 'vuex'
import { computed } from "vue";
export default {
name: 'test',
setup () {
const store = useStore()
let count = computed(() => { return store.state.count });
const clickHandle = () => {
store.dispatch('setCount', 3)
store.dispatch('count/setCount', 3)
}
const changeHandle = () => {
store.dispatch('setUserInfo', 'xiaofang')
store.dispatch('user/setUserInfo', 'xiaofang')
}
return {
count,
clickHandle,
changeHandle
}
}
};
</script>
和前面例子的区别在于: 
全局模块和局部模块
全局模块和局部模块引入方式不同,如下: src/store/index.ts:
import { createStore } from 'vuex'
import count from './modules/count'
import user from './modules/user'
export default createStore({
...user,
modules:{
count
},
})
注意:全局模块 /modules/user.ts 中不需要开启命名空间。
组件中使用方式也发生了变化:
<template>
<div>
<!-- 不带命名空间 -->
<h1>vuex数据-state count、getters:{{$store.getters['count/getCount']}}</h1>
<h1>vuex数据-state user、getters:{{$store.getters.getUserInfo}}</h1>
<h1>count:{{count}}</h1>
<a-button @click="clickHandle">点击修改count</a-button>
<a-button @click="changeHandle">点击修改用户信息</a-button>
</div>
</template>
<script>
import { useStore } from 'vuex'
import { computed } from "vue";
export default {
name: 'test',
setup () {
const store = useStore()
let count = computed(() => { return store.state.count });
const clickHandle = () => {
store.dispatch('count/setCount', 3)
}
const changeHandle = () => {
store.dispatch('setUserInfo', 'xiaofang')
}
return {
count,
clickHandle,
changeHandle
}
}
};
</script>
|