Vuex的介绍与使用

#Vuex

一、介绍

1.1含义

​ Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

1.2 核心概念

  1. 单一状态树

​ Vuex 使用单一状态树——是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个“唯一数据源 (SSOT)”而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。

单一状态树的优势:

  • 如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难;
  • 所以Vuex也使用了单一状态树来管理应用层级的全部状态;
  • 单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护;

注意:

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。

  1. 应用

每一个 Vuex 应用的核心就是 store,里面又包括:

(1)state(数据):用来存放数据源,就是公共状态;
(2)getters(数据加工):有的时候需要对数据源进行加工,返回需要的数据;
(3)actions(事件):要执行的操作,可以进行同步或者异步事件
(4)mutations(执行):操作结束之后,actions通过commit更新state数据源
(5)modules:使用单一状态树,致使应用的全部状态集中到一个很大的对象,所以把每个模块的局部状态分装使每一个模块拥有本身的 state、mutation、action、getters、甚至是嵌套子模块

1.3 工作流程

(1)通过dispatch去提交一个actions,
(2) actions接收到这个事件之后,在actions中可以执行一些异步|同步操作,根据不同的情况去分发给不同的mutations,
(3)actions通过commit去触发mutations,
(4)mutations去更新state数据,state更新之后,就会通知vue进行渲染。

二、Vuex的使用

使用的软件为 Visual Studio Code ,并且已经安装好 node.js,yarn。本文不提供安装方法。如需安装,移步。

  1. 安装vuex
yarn add vuex
  1. 在src目录下创建一个store目录,在该目录下创建index.js文件,用于创建Store对象
    在这里插入图片描述
//用于创建Vuex的核心对象Store
//1.导入
import {createStore } from 'vuex'


//2.创建Store对象
const store = createStore({
//state 用于存储数据
state(){
return {
count:1,
}
},
//actions 用于响应组件中的事件
actions:{

},
//mutations 用于操作数据
mutations:{

}
});

//3.暴露出store对象
export default store;
  1. 在main.js 使用store对象

    import store from './store';
    app.use(store);
    
  2. 在 Vue 组件中, 可以通过this.$store 访问store实例 (选项式)

    <template>
    <h2>{{$store.state.count}}</h2>
    </template>
    
    <script>
    export default {
    name: 'App',
    data() {
    return {
    
    };
    },
    components: {
    },
    methods: {
    
    },
    mounted() {
    console.log(this.$store.state.count);
    }
    };
    </script>
    
    <style lang="css" scoped>
    </style>
    
    1. 在 Vue 组件中, 可以通过useStore函数来使用store(组合式)
    <template>
      <h2>{{ count }}</h2>
    </template>
    
    <script setup>
    import { computed } from 'vue';
    import { useStore } from 'vuex';
    
    const store = useStore();
    const count = computed(() => store.state.count);
    </script>
    
    <style lang="css" scoped>
    </style>
    

三、辅助函数

3.1 mapState辅助函数

 computed:mapState({
        
        //箭头函数可使代码更简练
        name: state => state.name,
        // 传字符串参数 'name' 等同于 `state => state.name`
        //给name定义一个别名
        xingming: 'name',
        //扩展函数,可以对name进行操作
        namePlusLocalState (state) {
            return this.hello + state.name;
        },
        sex:state=>state.sex,
        age:state=>state.age,
    }),

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组

 computed:mapState(["name","sex","age"]),

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符,我们可以极大地简化写法

x 1//对象展开运算符2computed:{3    //局部计算属性4    localComputed () { /* ... */ },5    ...mapState(["name","sex","age"]),6},

3.2 mapGetters辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:

<template>
    <div>
        <h2>总价:{{totalPrice}}</h2>
        <h2>书籍信息:{{getBookById(3)}}</h2>
    </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
    name: 'Book',
    computed:{
        ...mapGetters(['totalPrice','getBookById']),
    },
};
</script>

<style lang="scss" scoped>

</style>

3.3 mapMutations的辅助函数

<template>
    <div class="box">
        <h2>和:{{$store.state.sum}} --{{count}}</h2>
        <input type="number" length="3" v-model="num"/>
        <input type="button" value="+" @click="add({value:num})"/>
        <input type="button" value="-" @click="sub({value:num})"/>
        <Counter/>
    </div>
</template>

<script>
import {mapMutations } from 'vuex'
export default {
    name: 'CalcSum',

    data() {
        return {
            num:1,
        };
    },

    mounted() {
        
    },
    methods: {
        /*
        add(){
            //通过dispatch去提交一个action
            this.$store.dispatch('increment', this.num);
            console.log(this.$store.state.sum)
            //强制刷新页面
            //this.$forceUpdate();
        },
        sub(){
            this.$store.dispatch('decrement', this.num);
            //this.$forceUpdate();
        },*/
        
        ...mapMutations({
            add:'INCREMENT',
            sub:'DECREMENT'
        }),
    },
    computed: {
        count () {
             return this.$store.state.sum
        }
    }
};
</script>

<style lang="css" scoped>
    .box{
        width:70%;
        margin: auto;
    }
</style>

如果组件的事件函数名与Mutation中修改状态的函数名一样,我们可以简写:

...mapMutations(['INCREMENT','DECREMENT']),

mutation重要原则:

​ 一条重要的原则就是要记住 mutation 必须是同步函数,这是因为devtool工具会记录mutation的日记;每一条mutation被记录,devtools都需要捕捉到前一状态和后一状态的快照;但是在mutation中执行异步操作,就无法追踪到数据的变化;

3.4 actions的辅助函数

action也有对应的辅助函数:使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store
在这里插入图片描述

四、vuex持久化

4.1 使用持久化原因

Vue项目中使用Vuex作为状态管理,相当于全局的变量存储,可以在所有的vue组件中共享数据、动态修改其状态。vuex是单向数据流,存在vuex中的变量都是响应式数据,组件中一般会通过computed来使用store中的状态、且有缓存

​ 但是当我们去刷新浏览器的时候,store中的状态都会被清空、重新初始化为最初的状态,在某些情况下,我们可能需要将这些状态保存下来,如何让vuex或pinia的状态持久化存储?

​ 要实现持久化存储,简单来说就是将其状态保存到localStorage或者sessionStorage中 .然后在给每个状态默认值的时候就从localStorage或sessionStorage中取就可以了也就是咱们直接手写实现,另外一种方式就是使用第三方插件(vuex-persistedstate或者vuex-persist)

4.2 vuex-persistedstate的使用

  1. 安装vuex-persistedstate

    #npm 安装
    npm install vuex-persistedstate
    #yarn 安装
    yarn add vuex-persistedstate
    
  2. 在vuex的配置文件store/index.js进行配置:

    //1.导入
    import {createStore } from 'vuex'
    import createPersistedState from "vuex-persistedstate";
    
    const store = createStore({
        state(){
            return {
                count:0
            }
        },
        getters:{
    
        },
        actions:{
            add(context,value){
                console.log(value);
                setTimeout(() => {
                    context.commit("setCount",1)
                }, 1000);
                
            },
            sub(context,value){
                context.commit("setCount",-1)
            }
        },
        mutations:{
            setCount(store,value){
                store.count += value
            }
        },
        plugins:[
            createPersistedState({
                // 存储方式:localStorage、sessionStorage、cookies
                storage: window.sessionStorage,
                // 存储的 key 的key值
                key: "store",
                reducer(state) { //render错误修改
                  // 要存储的数据:本项目采用es6扩展运算符的方式存储了state中所有的数据
                  return { ...state };
                }
              })
        ]
    
    });
    
    export default store;
    

    上面是将所有的store中的state状态都持久化存储了。

    如果是想只持久化某一个模块的数据,则将上面plugins修改为下面写法

    plugins:[
            createPersistedState({
                // 存储方式:localStorage、sessionStorage、cookies
                storage: window.sessionStorage,
                // 存储的 key 的key值
                key: "store",
                // reducer(state) { //render错误修改
                //   // 要存储的数据:本项目采用es6扩展运算符的方式存储了state中所有的数据
                //   return { ...state };
                // }
                 // 只持久化存储user模块的状态
                paths: ['user']
              })
        ]
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值