Vuex是一个专为Vue.js应用程序开发的状态管理模式。
官网:https://next.vuex.vuejs.org/
Vuex的几个核心概念
安装依赖
npm install vuex@next --save
# 或者
yarn add vuex@next --save
src目录下新建一个Vuex的目录,Vuex目录里面新建一个store.js
import {
createStore} from 'vuex';
const store=createStore({
state(){
// 定义数据
return{
count:1
}
},
mutations:{
// 定义方法
incCount(state){
state.count++;
}
}
});
export default store;
main.ts挂载store.js
import {
createApp} from 'vue'
import App from '@/App.vue'
import router from "@/router";// 引入router
import store from "@/Vuex/store.js";
const app = createApp(App);
app.use(router);//挂载使用router
app.use(store);// 挂载Vuex的store
app.mount('#app')
第一种获取State的方法(不推荐)
用到的组件里面引用store,然后计算属性里面获取 (单页面组件引用)
computed:{
count(){
return store.state.count
}
}
第二种获取State的方法
由于全局配置了Vuex app.use(store)。所以直接可以通过下面的方法获取store里面的值。
computed:{
count(){
return this.$store.state.count
}
}
获取store中的list
<template>
<ul>
<li v-for="(item,index) in $store.state.list" :key="index">
{
{item}}
li>
ul>
template>
第三中获取State的方法-通过mapState助手
调用的组件中引入mapState
import {
mapState} from "vuex"
方法1:store中的变量与组件中的变量名称不一致,使用箭头函数做映射
方法2:store中的变量与组件中的变量名一样可以直接这样使用
computed: {
// 方法1
...mapState({
thisCount: (state) => state.count,
thisBanner: (state) => state.banner,
thisList: (state) => state.list,
}),
//方法2
...mapState(["count","banner","list"])
}
在模板中调用:
<template>
<h3>mapState获取store中的数据(方法1)h3>
thisCount:{
{ thisCount }}
<br>
thisBanner:{
{ thisBanner }}
<br>
<ul>
<li v-for="(item,index) in thisList" :key="index">
{
{ item }}
li>
ul>
<hr>
<h3>mapState获取store中的数据(方法2)h3>
count:{
{ count }}
<br>
banner:{
{ banner }}
<br>
<ul>
<li v-for="(item,index) in list" :key="index">
{
{ item }}
li>
ul>
template>
定义Getter
const store = createStore({
state() {
// 数据
return {
count: 1,
banner: "zws",
list: ["文件", "编辑", "视图"],
msg: "你好store"
}
},
mutations: {
// 方法,可以改变state里面的数据
incCount(state) {
state.count++;
},
setCount(state, num) {
state.count += num;
},
setBanner(state) {
state.banner = "改变后的banner"
}
},
getters: {
revMsg(state) {
return state.msg.split("").reverse().join("");
},
num(state) {
return state.count + 10;
}
}
});
访问Getter的方法
方法一:Getter会暴露为store.getter对象,你可以以属性的形式访问这些值:
<template>
{
{$store.getters.num}}
template>
方法二:使用计算属性
computed:{
count(){
return this.$store.state.count
},
banner(){
return this.$store.state.banner
},
revMsg(){
return this.$store.getters.revMsg;
},
num(){
return this.$store.getters.num;
}
}
方法三:通过mapGetters辅助函数
import {
mapState,mapGetters} from "vuex"
computed: {
// 方法1
...mapState({
thisCount: (state) => state.count,
thisBanner: (state) => state.banner,
thisList: (state) => state.list,
}),
//方法2
...mapState(["count","banner","list"]),
// 使用对象展开运算符...mapGetters混入computed处对象中
// 方法1
...mapGetters([
"num","revMsg"
]),
// 方法2
// 给store中的getters取个别名
...mapGetters({
thisMsg: "revMsg",
thisNum: "num",
}),
}
template中使用
<template>
<h3>mapGetters获取store中的getters(方法1)h3>
revMsg:{
{revMsg}}
<br>
num:{
{num}}
<br>
<h3>mapGetters获取store中的getters(方法2)h3>
revMsg:{
{thisMsg}}
<br>
num:{
{thisNum}}
template>
更改Vuex的store中的状态唯一的方法时提交mutation。Vuex中的mutation非常类似于事件:每个mutation都有一个字符串类型的事件类型(type)和一个回调函数(handler)。这个回到函数就是我们实际进行状态更改的地方,并且它会接收state作为第一个参数。
定义Mutations触发Mutations里面的方法
const store=createStore({
state(){
return{
count:1
}
},
mutations:{
incCount(state){
// mutate state
state.count++;
}
}
});
触发mutations里面的方法:
this.$store.commit('incCount')
执行方法传入参数:
const store=createStore({
state(){
// 数据
return{
count:1,
myname:"zws"
}
},
mutations:{
// 方法,可以改变state里面的数据
incCount(state){
state.count++;
},
setCount(state,num){
state.count+=num;
},
setMyName(state){
state.myname="改变后的zws"
}
}
});
触发方法:
this.$store.commit("setCount",15);
store.js中定义Actions
const store = createStore({
state() {
// 数据
return {
count: 1,
banner: "zws",
list: ["文件", "编辑", "视图"],
msg: "你好store"
}
},
mutations: {
// 方法,可以改变state里面的数据
incCount(state) {
state.count++;
},
setCount(state, num) {
state.count += num;
},
setBanner(state, msg) {
state.banner = "改变后的banner" + msg;
}
},
getters: {
revMsg(state) {
return state.msg.split("").reverse().join("");
},
num(state) {
return state.count + 10;
}
},
actions: {
// 主要用于执行Mutations里面的方法,异步操作放在这里
inCount(context) {
// 执行mutations里面的incCount方法
context.commit("incCount");
},
incSetBanner(context,msg) {
setTimeout(() => {
context.commit("setBanner", msg);
}, 1000);
},
// 另一种写法
/*incSetBanner({commit},msg) {
setTimeout(() => {
commit("setBanner", msg);
}, 1000);
},*/
}
});
触发Actions中的方法
store.dispatch("inCount");
store.dispatch("incSetBanner","zws");
乍一眼看上去感觉多此一举,我们直接分发mutations岂不是更方便?实际上并非如此,还记得mutations必须同步执行这个限制么?Actions就不受约束~!我们可以在actions内部执行异步操作
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。
为了解决以上问题,Vuex允许我们将store分割成模块(Modules)。每个模块拥有自己的state,mutations,actions,getters,甚至是嵌套子模块——从上至下进行同样的方式分割:
const moduleA = {
state: () => ({
... }),
mutations: {
... },
actions: {
... },
getters: {
... }
}
const moduleB = {
state: () => ({
... }),
mutations: {
... },
actions: {
... }
}
const store = createStore({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state
示例:
在Vuex目录新建userStore.js
let userStore = {
state() {
// 数据
return {
count: 1,
banner: "zws",
msg: "你好store"
}
},
mutations: {
// 方法,可以改变state里面的数据
incCount(state) {
state.count++;
},
setCount(state, num) {
state.count += num;
},
setBanner(state, msg) {
state.banner = "改变后的banner" + msg;
}
},
getters: {
revMsg(state) {
return state.msg.split("").reverse().join("");
},
num(state) {
return state.count + 10;
}
},
actions: {
// 主要用于执行Mutations里面的方法,异步操作放在这里
inCount(context) {
// 执行mutations里面的incCount方法
context.commit("incCount");
},
incSetBanner(context, msg) {
setTimeout(() => {
context.commit("setBanner", msg);
}, 1000);
},
}
}
export default userStore;
在Vuex目录新建newsStore.js
let newsStore = {
state() {
// 数据
return {
list: ["新闻1", "新闻2", "新闻3"],
count: 100
}
},
mutations: {
incCount(state) {
state.count++;
}
}
}
export default newsStore;
改造store.js
import {
createStore} from 'vuex';
import userStore from '@/Vuex/userStore';
import newsStore from "@/Vuex/newsStore";
const store = createStore({
modules:{
"user":userStore,
"news":newsStore
}
});
export default store;
在User.vue组件中使用userStore与newsStore的state数据与调用mutations里面的方法
<template>
<div>
<h1>User组件h1>
获取userStore里面的count:{
{$store.state.user.count}}
<br>
获取newsStore里面的count:{
{$store.state.news.count}}
获取newsStore里面的list:
<ul>
<li v-for="(item,index) in list" :key="index">
{
{item}}
li>
ul>
<br>
<br>
<button @click="incCount">调用mutations里面的方法button>
div>
template>
<script>
import {
defineComponent} from "vue";
export default defineComponent({
setup() {
return {
}
},
computed:{
list(){
return this.$store.state.news.list;
}
},
methods:{
incCount(){
// 调用mutations里面的方法
// 广播:userStore与newsStore里面的incCount都会执行
this.$store.commit("incCount");
}
}
});
script>
注意:如果多个store模块中定义有相同的方法名,调用的时候,都会被调用