vuex的工作流程,模块化使用案例分享,及状态持久化

简介: vuex的工作流程,模块化使用案例分享,及状态持久化

一、Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方生态系统中,并且在开发大型、复杂单页应用(SPA)时尤其有用。


二、核心概念

  • state:定义应用程序状态的数据。(数据,类似data)
  • mutations:用于修改状态的方法。(执行,类似methods)
  • actions:用于触发 mutations 的方法。(事件,类似controller)
  • getters:用于获取 state 中的数据。(数据加工,类似computed)


  • modules:使用单一状态树,致使应用的全部状态集中到一个很大的对象,所以把每个模块的局部状态分装使每一个模块拥有本身的 state、mutation、action、getters、甚至是嵌套子模块;


三、Vuex 的工作流程

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


四、什么情况下我应该使用 Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。


如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式 (opens new window)就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。


五、Vuex 的使用

  • 定义 state:定义应用程序的状态数据。
  • 定义 mutations:定义修改 state 的方法。
  • 定义 actions:定义触发 mutations 的方法,可以包含异步操作。
  • 定义 getters:定义获取 state 中数据的方法。
  • 创建 store:将 state、mutations、actions、getters 组合成一个 store 对象。
  • 在应用程序中使用 store:在应用程序中使用 store 对象的 state、mutations、actions、getters。

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:

  • 应用层级的状态应该集中到单个 store 对象中。
  • 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
  • 异步逻辑都应该封装到 action 里面。


只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。

对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。


六、使用示例

以购物车为例,介绍vuex的使用全过程。

// vuex的入口文件,封装了cart模块,直接引入使用

// store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import cart from './cart'
Vue.use(Vuex)
export default new Vuex.Store({
  modules: {cart}
})

// cart模块的首页,引入了getters,actions,mutations

// 以及state中模拟的数据

// store/cart/index.js

import getters from "./getters"
import actions from "./actions"
import mutations from "./mutations"

export default {
    state:{
        goods: [{
            id:1,
            name:'小米手机',
            price: 2000,
            count: 0,
        },{
            id:2,
            name:'苹果手机',
            price: 3000,
            count: 0,
        },{
            id:3,
            name:'华为手机',
            price: 4000,
            count: 0,
        }],
    },
    getters,
    actions,
    mutations
}

// getters文件,计算购物车的总价及数量

// store/cart/getters.js

export default {
  totalPrice(state){
    return state.goods.reduce((total,item)=>{
      total += item.price * item.count
      return total
    },0).toFixed(2)
  },
  count(state){
    return state.goods.reduce((total,item)=>{
      total += item.count
      return total
    },0)
  }
}

// actions文件,用于提交商品数量的变化

// store/cart/actions.js

export default {
    add({commit},payload){
        commit('add',payload)
    },
    reduce({commit},payload){
        commit('reduce',payload)
    }
}

// mutations文件,用于改变state中商品的数量变化

// store/cart/mutations.js

export default {
    add(state,index){
        state.goods[index].count++
    },
    reduce(state,index){
        if(state.goods[index].count>=1){
            state.goods[index].count--
        }
    },
}

// 这里是使用vuex的页面,展示购物车页面

// app.vue

<template>
  <div class="about">
    <div v-for="(item, index) in goods" :key="index">
      <div>{{ item.name }}</div>
      <div>{{ item.price }}</div>
      <div style="display: flex">
        <button @click="reduce(index)">-</button>
        <div>{{ item.count }}</div>
        <button @click="add(index)">+</button>
      </div>
    </div>
    <div style="display: flex;">
      <div>总计:{{ count }}</div>
      <div>结算:{{ totalPrice }}</div>
    </div>
  </div>
</template>

<script>
import { mapGetters,mapState } from 'vuex'
export default {
  computed: {
    ...mapState({
      goods(state) {
        return state.cart.goods
      },
    }),
    ...mapGetters(['count', 'totalPrice'])
  },
  methods: {
    add(index) {
      this.$store.dispatch('add', index)
    },
    reduce(index) {
      this.$store.dispatch('reduce', index)
    }
  }
}
</script>


七、状态持久化

vuex优势: 相比sessionStorage,存储数据更安全,sessionStorage可以在控制台被看到。

vuex劣势: 在F5刷新页面后,vuex会重新更新state,所以,存储的数据会丢失。(即刷新浏览器,vuex数据丢失)


1、手动利用HTML5的本地存储

vuex的state在localStorage或sessionStorage或其它存储方式中取值 在mutations定义的方法里对vuex的状态操作的同时对存储也做对应的操作。这样state就会和存储一起存在并且与vuex同步


2、利用vuex-persistedstate插件

2.1、安装
npm install vuex-persistedstate
2.2、配置
  • vuex-persistedstate默认存储于localStorage
// 在store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
 
Vue.use(Vuex);
 
export default new Vuex.Store({
  // ...
  plugins: [createPersistedState()]
  // ...
});
  • 存储sessionStorage的情况
plugins: [
    createPersistedState({
      storage: window.sessionStorage
    })
  ]
  • 存储cookie的情况
import Cookies from 'js-cookie'

plugins: [
    persistedState({
      storage: {
        getItem: key => Cookies.get(key),
        setItem: (key, value) => Cookies.set(key, value, { 
          expires: 7 
        }),
        removeItem: key => Cookies.remove(key)
      }
    })
  ]

指定需要持久化的state

在vuex-persistedstate中,如果你想要指定需要持久化的state(即只持久化Vuex store中的部分状态,而不是全部),你可以通过paths配置选项来实现。paths是一个数组,其中的每个元素都是一个字符串,表示Vuex store中需要被持久化的状态的路径。

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import cart from './cart'
import user from './user'
Vue.use(Vuex)
export default new Vuex.Store({
  plugins: [
    createPersistedState({
      paths:['cart','userSettings','user.name'] 
      // 持久化'cart'模块的全部状态
      // 持久化全局状态中的'userSettings'
      // 只持久化'user'模块中的'name' 
    })
  ],
  state: {  
    // 你的全局状态  
    token: '',  
    userSettings: {  
      theme: 'dark',  
      notifications: true  
    }  
  },  
  // 你的模块  
  modules: {cart,user}
})

过滤需要持久化的state

在vuex-persistedstate中,reducer是一个可选的配置项,它的作用是对即将被持久化到存储(如localStorage或sessionStorage)中的Vuex状态进行过滤或转换。通过使用reducer,你可以控制哪些数据被保存,以及如何保存这些数据,从而实现更细粒度的状态持久化控制。

reducer通常是一个函数,它接收当前的state(或特定部分的state,取决于你的配置)作为参数,并返回一个新的对象,该对象包含了应该被持久化的数据。


plugins: [
    createPersistedState({
        storage: window.sessionStorage,
        reducer(state) {  
          // 只返回需要被持久化的部分state  
            return {  
                // 假设我们只想持久化user模块中的name和avatar字段  
                user: {  
                  name: state.user.name,  
                  avatar: state.user.avatar  
                }  
            };  
        }
    })
  ]

如果path和reducer同时存在则使用reducer, 忽悠paths属性。

  • API 配置

createPersistedState([options])使用给定的选项创建插件的新实例。可以提供以下选项来配置您的特定需求的插件:

API 参数类型 说明 默认值
key String 用于存储持久状态的键。 vuex
paths Array 部分保持状态的任何路径的数组。如果没有给定路径,则完整状态将持久化。如果给定一个空数组,则不会持久化任何状态。如果使用模块,请包括模块名称。 []
reducer Function 一个将被调用的函数,对即将被持久化到存储中的Vuex状态进行过滤或转换。 都包含这些值
subscriber Function 被调用以设置突变订阅的函数。 store => handler => store.subscribe(handler)
storage String 指定存储数据的方式。 localStorage
getState Function 用来重新补充先前持久状态的功能。 storage
setState Function 用以保持给定状态的函数。 storage
filter Function 一个将被调用以过滤setState最终将在存储中筛选过滤的函数。 () => true

注意,getState 和 setState 是高级选项,它们允许你完全控制状态的存储和恢复过程。然而,在大多数情况下,简单地使用 paths 或默认行为可能就足够了。

目录
相关文章
|
6月前
|
JavaScript 数据中心
Vuex工作机制
Vuex工作机制
37 0
|
JavaScript API
Vuex状态管理最佳实践
使用Vuex进行状态管理时,有一些最佳实践可以帮助你保持代码清晰、可维护和高效。以下是一些详细的Vuex状态管理最佳实践
159 3
|
25天前
|
存储 缓存 前端开发
Vuex深入探究:前端状态管理的利器
【10月更文挑战第11天】Vuex深入探究:前端状态管理的利器
21 1
|
25天前
|
存储 JavaScript 前端开发
Redux 状态管理入门
本文介绍了 Redux,一个广泛使用的 JavaScript 状态管理库,重点讲解了其核心概念(如 Store、Action、Reducer 等)、基本使用方法、常见问题及解决策略,并通过代码示例详细说明了如何在 React 应用中集成和使用 Redux。
21 1
|
6月前
|
存储 资源调度 JavaScript
阿珊解析Vuex:实现状态管理的利器
阿珊解析Vuex:实现状态管理的利器
|
3月前
|
存储 JavaScript 前端开发
不要滥用Pinia和Redux了!多组件之间交互可以手写一个调度器!
【8月更文挑战第24天】不要滥用Pinia和Redux了!多组件之间交互可以手写一个调度器!
55 2
不要滥用Pinia和Redux了!多组件之间交互可以手写一个调度器!
|
3月前
|
设计模式 JavaScript 安全
MobX状态管理:简洁而强大的状态机
MobX 是一种简洁高效的状态管理库,通过声明式的方式管理应用状态,使数据变化自动同步到视图。它利用 `@observable` 创建响应式数据,`@computed` 实现自动更新的计算属性,`@action` 确保状态安全变更。结合 `mobx-react`,可在 React 组件中使用 `observer` 自动响应状态更新。MobX 内部采用代理与访问者模式追踪依赖,确保最小化更新,提升性能。支持 TypeScript,提供类型安全与代码提示。
63 2
|
6月前
|
存储 前端开发 JavaScript
【思维扩展】状态机与 React 中的状态
【思维扩展】状态机与 React 中的状态
|
6月前
|
JavaScript 前端开发
【干货分享】轻松入门 Redux:解密状态管理的神奇世界
【干货分享】轻松入门 Redux:解密状态管理的神奇世界