24.Vue状态管理Vuex

一、Vuex

Vuex是一个专为Vue.js应用程序开发的状态管理模式。

官网:https://next.vuex.vuejs.org/

主要功能:
  1. Vuex可以实现Vue不同组件之间的状态共享(解决了不同组件之间的数据共享)
  2. 可以实现组件里面的数据持久化

Vuex的几个核心概念

  • State 主要用于定义数据
  • Getters 与前面的计算属性类似,用于vuex中计算属性
  • Mutations 主要用于定义方法,改变state中的数据
  • Actions 主要用于执行Mutations的方法,用于异步操作
  • Modules
二、Vuex的基本使用
  1. 安装依赖

    npm install vuex@next --save
    # 或者
    yarn add vuex@next --save
    
  2. src目录下新建一个Vuex的目录,Vuex目录里面新建一个store.js

import {createStore} from 'vuex';
const store=createStore({
    state(){
        // 定义数据
        return{
            count:1
        }
    },
    mutations:{
        // 定义方法
        incCount(state){
            state.count++;
        }
    }
});

export default store;
  1. 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')
    
三、Vuex中的State
  1. 第一种获取State的方法(不推荐)

    用到的组件里面引用store,然后计算属性里面获取 (单页面组件引用)

    computed:{
        count(){
            return store.state.count
        }
    }
    
  2. 第二种获取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>
    
  3. 第三中获取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>
    
四、Vuex中的Getter
  1. 定义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;
            }
        }
    });
    
  2. 访问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中的Mutations

更改Vuex的store中的状态唯一的方法时提交mutation。Vuex中的mutation非常类似于事件:每个mutation都有一个字符串类型的事件类型(type)和一个回调函数(handler)。这个回到函数就是我们实际进行状态更改的地方,并且它会接收state作为第一个参数。

  1. 定义Mutations触发Mutations里面的方法

    const store=createStore({
        state(){       
            return{
                count:1
            }
        },
        mutations:{       
            incCount(state){
                 // mutate state
                state.count++;
            }
        }
    });
    

    触发mutations里面的方法:

    this.$store.commit('incCount')
    
  2. 执行方法传入参数:

    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);
    
六、Vuex中的Actions
  1. 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);
            },*/
        }
    });
    
  2. 触发Actions中的方法

    store.dispatch("inCount");
    store.dispatch("incSetBanner","zws");
    

    乍一眼看上去感觉多此一举,我们直接分发mutations岂不是更方便?实际上并非如此,还记得mutations必须同步执行这个限制么?Actions就不受约束~!我们可以在actions内部执行异步操作

七、Vuex中的Modules

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,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模块中定义有相同的方法名,调用的时候,都会被调用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值