Vuex _ 核心插件

56 篇文章 4 订阅

目录

一、Vuex

1.1、概述

1.2、Vuex 核心概念

1.3、安装与配置

1.4、在组件中获取 Vuex 中的数据

1.5、moutations 同步修改 state

1.6、actions 配置 mutations 异步修改 state 数据

1.7、getters

1.8、modules 模块化

1.9、辅助函数

图例 :


我是因为啥才去用的 Vuex 呢 ?

一开始搭建项目,初期建设嘛,老前端提议说这个项目没那么大,用不着再引进来个 

Vuex 库了,意思好像是说这个 Vuex 库会很大,轻易的话就不要引入项目了,就使用 

Event Bus 事件总线 来处理就够用了 , 但是吧 , 项目写着写着 ,项目目录越来越多 ,

甚至到了后期阶段性优化 , 以及细拆分组件时 , 导致数据传递起来越来越不方便了 ,

就感觉有必要引入 Vuex 来管理数据了。

引用 Redux 的作者 Dan Abramov 的话说就是 :

Flux 架构就像眼镜:您自会知道什么时候需要它。


一、Vuex

1.1、概述

Vuex 是什么? | Vuex

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式 ,Vuex 是实现 组件 全局状态数据 ) 管理 的一种 机制 ,可以方便的 实现组件之间 的 数据共享 。如果您不打算 开发 大型 单页 应用,使用 Vuex 可能是繁琐冗余的 。如果您的应用 够简单,最好不要使用 Vuex 。

使用 Vuex 管理数据 优势 :

  • 能够在 Vuex 中 集中管理 共享的数据 ,便于 开发 和 后期 进行 维护
  • 能够高效的 实现组件之间 的  数据共享  ,提高 开发效率
  • 存储在 Vuex 中的数据是 响应式 的 ,当数据发生改变时 ,页面中的 视图 也会 同步更新 
  • Vuex 中的 数据 操作 可以在开发阶段 通过开发调试工具 devtools 来进行追踪 ,便于开发


1.2、Vuex 核心概念

Vuex 对象中通过  state  来 存储 状态 ,除了 state 以外还有

用来 操作 ( mutations )  state 中数据的 方法集 ,以及当我们需要

对 state 中的 数据 需要 加工 ( getters ) 的 方法集 等等 成员 。

成员列表:

  • state            存放 状态 ( 数据 )       必须的
  • mutations   state 成员操作 --  修改 state 中的 数据    同步 操作
  • getters     加工 state 成员给外界  -- 获取 state 中的数据,类似于组件中的  计算属性
  • actions   异步 操作 在 Vuex 中可以进行 异步操作(ajax)异步操作不能直接修改 state
  • modules   模块化状态管理  多状态文件 管理时使用

Vuex 工作流程 :

 

首先 ,Vue Components( Vue 组件 )如果调用某个 VueX 的方法过程中需要向 后端 发送请求时 ( Backend API ) 或者 说出现 异步操作 时 ,则走上面的分支流程 :需要先 Dispatch ( 派发 ) VueX 中  Actions 内编写的方法 ,以保证数据的同步。可以说,Actions  的存在就是为了让  Mutations 中的方法能在 异步 操作 中起作用 。( 可理解 : 把异步 转成了 同步 )

如果没有 异步操作 ,那么我们就可以直接在 组件内 提交 状态中的 Mutations 中自己 编写 的 方法 来达成对 state 成员的 修改 操作 。


面试点 : 我可以直接修改 state 中的数据么 ? 

因为 state 本身其实就是一个对象而已 , 所以按理是能够直接修改 state 中的数据 , 但是 ! 我们极其 不建议 在组件中直接对 state 中的成员进行操作 ,这是因为 直接修改 ( 例如:this.$store.state.name = 'hello' )  的话不能被 Vue Devtools ( 开发者工具 ) 所监控到 。最后被修改后的 state 成员会被 渲染到组件的 原位置当中去。( 无法实时同步响应更新视图 )


1.3、安装与配置

  • 方案1:在使用 vue-cli 命令创建项目时,勾选上 Vuex 选项,即安装上 Vuex 插件 ( 推荐 )

  • 方案2:通过后续的 npm 来进行安装

通过 npm 安装

$   npm i -S vuex

 手动创建仓库文件 

一般是在项目的  src( 根目录 )/ store( 数据仓库 )/ index.js

index.js  就是 vuex 的 仓库 文件

( 当然 , 你要是勾选上了 Vuex  插件的话 , 这些操作都会自动帮你创建弄好了的 )

在一个模块化的打包系统中,必须显式地通过 Vue.use() 插件 来安装 Vuex

① 引入 Vue 和 Vuex , 将 Vuex 使用 use 插件的方式 挂载到 Vue 上

② 通过 new 关键字 创建一个 Store 的 实例 ,

做好全局配置 ( 定义了全局 统一的、唯一的 数据源 )

③ 导出这个 store 实例对象

④ 在 main.js  ( 主入口文件 ) 内 , 在 Vue 的实例上 挂载 store

为了在 Vue 组件中访问  this.$store   property ,

你需要为 Vue 实例提供创建好的 store 。

Vuex 提供了一个从 根组件 向 所有 子组件 ,

以 store 选项的方式 “ 注 入 ” 该 store 的机制 :

// Vuex 状态管理入口文件
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 核心配置
export default new Vuex.Store({
  // 定义全局统一数据源
  state: {
    // 存放状态 ( 数据 )
  },
  mutations: {
    // state 成员操作 -- 修改 state 中的数据   同步操作
  },
  actions: {
    // 异步操作  异步操作 在 Vuex 中可以进行异步操作(ajax),异步操作不能修改 state
  },
  getters: {
  // 加工 state 成员给外界  -- 获取 state 中的数据,类似于组件中的 计算属性
  },
  modules: {
  // 模块化状态管理  多状态文件管理时使用
  }
})

1.4、在组件中获取 Vuex 中的数据

1、在 组件中 可以通过  this.$store.state.xxx  得到 Vuex 中 state 内的 数据 ,

2、在 组件中 一般通过  计算属性 ( computed ) 获取 。( 推荐 )


1.5、moutations 同步修改 state

mutations 同步 修改 state 数据 ,不能进行 异步

巧记 :

右侧组件 commit 的 参数 1 都是对应 mutations 内的 方法名称 ( ' incr ' ) ,

右侧组件 commit 的 参数 2 都是对应 mutations 内的 参数2 数据 ( 10 ) ;

左侧 Vuex 内 mutations 内 方法名称的对应函数 ( incr ) ,

参数 1 都是 state ( Vuex 的 state数据源 ) ,

参数 2 都是 commit 传过来的 参数 2 对应的 数据


1.6、actions 配置 mutations 异步修改 state 数据

在组件生命周期中初始化时通过 dispatch 发送指令 给 actions 来完成 异步 请求 。

请求得到数据后,通过 commit  方法 通知 mutations 修改 state 数据 state 数据又是响应式 。而组件中通过 计算属性 获取数据,所以就 实时更新 数据状态 

组件中 发送  dispatch  和 展示

巧记 :

右侧组件 dispatch参数 1 都是对应 actions 内的  方法名称 ( ' fetchUser ' ) ,  

右侧组件 dispatch参数 2 都是对应 actions 内的  参数2 数据 ; ( 1 )

左侧 Vuex 内 actions 内 方法名称的对应函数 ( fetchUser ) ,

参数 1 是 store ( 可将我们需要用到的 { commit } 解构出来单独使用 ) ,

参数 2 是 dispatch 传递过来的 参数 2 的数据 (可选参数)


巧记 :

下面 异步操作的 ( actions 内的 )  commit  的

参数 1 都是 方法名称 ( ' setUsers ' ) ,

参数 2 都是 数据  ( 异步请求回来的数据 ret ) ;

上面 同步操作的 ( mutations内的 )方法名称 对应的函数 ( setUsers ) ,

参数 1 都是 state ( Vuex 的 state数据源 ) ,

参数 2 都是 commit 传过来的 参数 2 对应的 数据 ( ret => payload )


1.7、getters

类似于 组件中计算属性 computed

 this.$store.getters.xxx 


1.8、modules 模块化

模块化 ,在 大型项目 中 会用到 ,把 state 数据 拆分到不同的 modules 模块中 ( 不同文件中 )

把原来也在 Vue.stroe 实例配置中的代码 ,拆分提取到不同的 业务文件 中

默认 模块化 没有开启强制 命名空间  : :

namespaced: true  开启强制命名空间  写法  : :


自动导入 Vuex 中的模块 :

知识点 :

JavaScript _ Object.keys( )_雨季mo浅忆的博客-CSDN博客


reduce _ 高阶函数 之 聚合运算_雨季mo浅忆的博客-CSDN博客


ES5 和 ES6新增_雨季mo浅忆的博客-CSDN博客


正则表达式 _ 基础版_雨季mo浅忆的博客-CSDN博客

9. 字符串和正则合作的方法

// 自动导入 Vuex 中的模块
let moduleFn = require.context('./modules', false, /\.js$/i)
console.log(moduleFn) // 是一个函数 : f webpackContext(req) {...}
// webpackContext.keys = function webpackContextKeys() { return Object.keys(map) }
console.log(moduleFn.keys()) // 是一个数组 : [ "./count.js", "./films.js", "./xxx.js"]

let modules = moduleFn.keys().reduce((prev, curr) => {
  console.log(prev, curr)
  // {} ,  "./count.js"
  // {count: {...}} ,  "./films.js"
  // {count: {...}}, films: {...} ,  "./xxx.js"
  let value = { ...moduleFn(curr).default, namespaced: true }
  // 字符串方法和正则表达式中的分组
  console.log(curr.match(/\.\/(\w+)\.js/i))
  // (2) ["./count.js", "count", index: 0, input: "./count.js", group: undefined]
  // (2) ["./films.js", "films", index: 0, input: "./films.js", group: undefined]
  // (2) ["./xxx.js", "xxx", index: 0, input: "./xxx.js", group: undefined]
  let key = curr.match(/\.\/(\w+)\.js/i)[1]
  console.log(key)
  // count
  // films
  // xxx
  prev[key] = value
  console.log(prev)
  // {count: {...}}
  // {count: {...}, films: {...}}
  // {count: {...}, films: {...}, xxx: {...}}
  return prev
}, {})


1.9、辅助函数

  • mapState
  • mapGetters
  • mapActions
  • mapMutations
  • 注:模块化后,开启了  namespaced: true  配置后 ,注意方法的调用有 2 个参数
  • 注意 : 后面 都有 s ,  是复数
  • 在 没有开启 命名空间时的 辅助函数写法

对象 ( 不常用 )

  • 有命名空间的写法


提升部分 ( 了 解 )   

自定义变量操作方法名 :

多行暴露 :

这里注意一点 : 

经测试好像是只能通过 多行暴露 或者 统一暴露 的形式将其导出

ECMAScript 6 _ 模块化_雨季mo浅忆的博客-CSDN博客_模块化开发理解

这里一定要注意看仔细了 :

经过本人后来测试 , 好像只有红线方案生效了, 黑色方案会产生报错

所以一定要这样使用 :

...mapMutations( ' 命名空间名称 ' , [ 变量名 ] )       这里 变量名 不要 加引号 “”

this.[ 变量名 ]( 参数 )       如此 调用 并 传参

否则  // 错误调用写法 " TypeError: this.xxx is not a function "


项目demo应用练习 :

src  /  store  /  index.js

// Vuex 状态管理入口文件
import Vue from "vue";
import Vuex from "vuex";
import demo from './modules/demo'

Vue.use(Vuex);

// 核心配置, 实例化一个 Vuex 状态
// Vuex 实例配置选项中的配置, 可以都不写, 但是 state 还是规定必须要有的
export default new Vuex.store({
  // 定义全局统一数据源
  state: {
    demo: "hello_Vuex",
  },
  // 加工 state 数据给外界 (Vuex 中的计算属性, 专门用于数据获取所用)
  getters: {
    getDemo(state) {
      return state.demo
    }
    // getDemo: state => state.demo
  },
  // 专门用于同步修改 state 中的数据操作
  mutations: {
    // state 参数1, 就是当前状态对象
    // 参数2, 组件内通过 commit 方法传过来的数据(可选参数)
    setDemo(state, payload) {
      state.demo = payload
    },
  },
  // 异步操作
  actions: {
    // updateDemo({ commit }, payload) {
    //  commit("setDemo", payload);
    // },
  },
  // 模块化状态管理
  modules: {
    // 模块化状态管理 多状态文件管理时使用
    /* 模块化后, state 它就会有命名空间, 获取时一定要加命名空间, 否则读取不到,
    但是默认 getters, mutations, actions, 它们没有命名空间, 只有你强制要求开启它们时, 它们才会有
    => namespaced: true 强制开启命名空间 */
    // key: value
    // key 就是命名空间名称, value 子模块对象
    // 这里注意如果是 外部文件的话一定要先引入进来才行
    demo
  }
});

src  /  store  /  modules  /  demo.js

export default {
  namespaced: true, // 开启命名空间
  state: {
    modulesDemo: '模块化里的_demo',
  },
  getters: {
    // getDemo(state) {
    //   return state.demo
    // },
    getModulesDemo: state => state.modulesDemo
  },
  mutations: {

  }
}

一、子组件内如何获取到 Vuex 中 state 内的数据

1、直接使用  this.$store.state.xxx  来获取

2、通过在 computed 计算属性中使用  this.$store.getters.xxx  去获取

3、使用 modules 模块化 后的获取方式

 this.$store.state.命名空间名称.xxx 

4、利用 辅助函数 来 获取

4-1、在 computed 计算属性 中使用 ...mapState 获取 ( 数组 | 对象

4-2、在 computed 计算属性 中使用 ...mapGetters 获取( 数组 | 对象 { 可自定义名称 } )

☆ 5、辅助函数 ...mapXxx  +  命名空间 namespaced  结合使用 来获取

5-1、...mapState ( 命名空间名称 , [ " state 内变量名 " ]

5-2、...mapGetters ( 命名空间名称 , [ " getters 内方法名 " ]

<template>
  <div></div>
</template>

<script>
// 4、利用辅助函数来获取
// 辅助函数使用 Vuex
// 在模块化中没有使用强制命名空间的用法
// mapState, mapGetters 写在 computed 计算属性 中
// mapMutations, mapActions 写在 methods 方法 中
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";

export default {
  mounted() {
    // 1. 组件内直接使用 this.$store.state.xxx 来获取
    console.log(this.$store.state.demo, "this.$store.state.demo");
    // 2. 获取 computed 计算属性中 返回的值
    console.log(this.getDemo, "this.getDemo");
    // 3-1. 模块化后的获取方式 - 直接获取
    console.log(
      this.$store.state.demo.modulesDemo,
      "this.$store.state.demo.modulesDemo"
    );
    // 3-2. 模块化后的获取方式 - 获取 computed 计算属性中 返回的值
    console.log(this.modulesGetDemo, "this.modulesGetDemo");
    // 4、利用辅助函数来获取
    console.log(this.demo, "辅助函数mapState_数组--this.demo");
    console.log(this.demo, "辅助函数mapState_对象--this.demo");
    console.log(this.getDemo, "辅助函数mapGetters_数组--this.getDemo");
    console.log(
      this.customDemo,
      "辅助函数mapGetters_对象(可自定义)--this.customDemo"
    );
    // 5 辅助函数 + 命名空间 结合起来 使用 来获取
    // 5-1 mapState
    console.log(
      this.modulesDemo,
      "辅助函数mapState_有命名空间--this.modulesDemo"
    );
    // 5-2 mapGetters
    console.log(
      this.getModulesDemo,
      "辅助函数mapGetters_有命名空间--this.getModulesDemo"
    );
  },
  computed: {
    // 2. 通过在 computed 计算属性中 return this.$store.getters.xxx
    getDemo() {
      return this.$store.getters.getDemo;
    },
    // 3-2. 通过在 computed 计算属性中 return this.$store.state.命名空间名称
    modulesGetDemo() {
      return this.$store.state.demo.modulesDemo;
    },
    /* 4. 通过它来获取 Vuex 中的 state 数据 */
    // 它支持两种写法, 数组 | 对象
    // 如果你没有开启强制命名空间, state 映射的名称为, 命名空间的名称, 调用为 .state 属性
    // 4-1 在 computed 计算属性中使用 mapState 数组的方式获取
    ...mapState(["demo"]),
    // 4-2 在 computed 计算属性中使用 mapState 对象的方式获取
    ...mapState({
      // key 在当前组件中使用的名称, value 是一个回调函数, 回调函数中的参数为模块化的对象
      demo: (state) => state.demo,
    }),
    // getters 因为没有强制开启, 直接就可读取里面的方法
    ...mapGetters(["getDemo"]), // 数组
    ...mapGetters({
      // 可自定义在当前组件中调用的变量名称
      customDemo: "getDemo",
    }), // 对象
    // 参数1: 命名空间名称, 参数2: state 中的属性
    // 5-1、...mapState ( 命名空间名称 , [ " state 内变量名 " ]
    ...mapState("demo", ["modulesDemo"]),
    // 5-2、...mapGetters ( 命名空间名称 , [ " getters 内方法名 " ]
    ...mapGetters("demo", ["getModulesDemo"]),
  },
};
</script>

<style lang="scss" scoped>
</style>


案例 _ todolist ( vuex )

异步 ( Vuex _ todolist )


图例 :


Vuex 中可能会需要的 utils :

( 1 ) : sessionStorage ( 会话存储 ) 封装方案 :

class SessionStorage {
// 获取
  get(key) {
    let value = sessionStorage.getItem(key) || ''
    if (/^[\[\{]/.test(value)) {
      value = JSON.parse(value)
    }
    return value
  }
// 设置
  set(key, value) {
    if (typeof value == 'object') {
      value = JSON.stringify(value)
    }
    sessionStorage.setItem(key, value)
  }
// 删除
  del(key) {
    sessionStorage.removeItem(key)
  }

}
// 默认导出一个 类 的 实例
export default new SessionStorage;

通过 storeage 来封装一些 操作 token 的 方法 :

import storage from './sessionStore'
const key = 'token'
// 设置 token 值
export const setToken = token => storage.set(key, token)
// 获取 token 值
export const getToken = () => storage.get(key)
// 判断是否含有 token 值
export const hasToken = () => storage.get(key) === '' ? false : true
// 删除 token 值
export const delToken = () => storage.del(key)

Vuex 项目中 高逼格 用法 总结 :

必须模块化 :辅助函数 + 命名空间 结合 使用

( 加点自动化语法 , 自动化导入 modules 中的文件模块 )

( 引入统一配置变量名文件 )

src  /  store  /  index.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

// 自动导入 Vuex 中的模块
let moduleFn = require.context("./modules", false, /\.js$/i);
let modules = moduleFn.keys().reduce((prev, curr) => {
  let value = { ...moduleFn(curr).default, namespaced: true };
  // 字符串方法和正则表达式中的分组
  let key = curr.match(/\.\/(\w+)\.js/i)[1];
  prev[key] = value;
  return prev;
}, {});

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  // 模块化配置
  modules,
});

src  /  store  /  typings.js

// 可自定义 N 多个操作变量
// ① 多行暴露
// export const SET_MAPNAME = "set_mapName";
// ② 统一暴露
const SET_MAPNAME = "set_mapName";

export { SET_MAPNAME };

src  /  store  /  modules  /  mapNameSpaced.js

// 引入变量名文件
import { SET_MAPNAME } from "../typings";

export default {
  // 强制开启命名空间
  // namespaced: true,
  state: {
    modulesMapName: "state--modules命名空间里的内容",
  },
  getters: {
    getModulesMapName: (state) => state.modulesMapName + "+++getModulesMapName",
  },
  mutations: {
    setModulesMapName(state, payload) {
      state.modulesMapName = payload;
    },
    // 变量名充当函数名
    [SET_MAPNAME](state, payload) {
      state.modulesMapName = payload;
    },
  },
  actions: {},
};

demo 任意子组件内

获取数据的操作方法 :

<template>
  <div>
    <p>{{ mapName }}</p>
    <p>{{ modulesMapName }}</p>
    <p>{{ getModulesMapName }}</p>
  </div>
</template>

<script>
import { mapState, mapGetters } from "vuex";
export default {
  data() {
    return {
      mapName: "子组件_辅助函数_命名空间",
    };
  },
  computed: {
    /* 获取操作 */
    // ...mapState( 命名空间名称 , [ "state 内变量名" ]
    ...mapState("mapNameSpaced", ["modulesMapName"]),
    // ...mapGetters( 命名空间名称 , [ "getters 内方法名" ]
    ...mapGetters("mapNameSpaced", ["getModulesMapName"]),
  },
  mounted() {
    console.log(this.modulesMapName, "this.modulesMapName");
    console.log(this.getModulesMapName, "this.getModulesMapName");
  },
};
</script>

<style lang="scss" scoped></style>


修改数据的操作方法 :

还可以通过 [ 变量名 ] 来调用方法进行修改操作 :


完整代码 :

<template>
  <div>
    <p>{{ mapName }}</p>
    <p>{{ modulesMapName }}</p>
    <p>{{ getModulesMapName }}</p>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations } from "vuex";
// 引入变量名文件
import { SET_MAPNAME } from "../store/typings";

export default {
  data() {
    return {
      mapName: "子组件_辅助函数_命名空间",
    };
  },
  computed: {
    /* 获取操作 */
    // ...mapState( 命名空间名称 , [ "state 内变量名" ]
    ...mapState("mapNameSpaced", ["modulesMapName"]),
    // ...mapGetters( 命名空间名称 , [ "getters 内方法名" ]
    ...mapGetters("mapNameSpaced", ["getModulesMapName"]),
  },
  mounted() {
    console.log(this.modulesMapName, "this.modulesMapName");
    console.log(this.getModulesMapName, "this.getModulesMapName");
    // 调用 mapMutations 获取到的修改方法
    // this.setModulesMapName("我是通过mapMutations来修改的");
    // 还可以通过变量名来调用方法进行修改操作 :
    this[SET_MAPNAME]("我是通过变量名来调用方法进行修改操作 :"); // 正确写法
    // this.SET_MAPNAME("我是通过变量名来调用方法进行修改操作 :"); // 错误调用写法"TypeError: this.xxx is not a function"
  },
  /* 修改操作 */
  methods: {
    // mapMutations 获取到修改方法
    // ...mapMutations("mapNameSpaced", ["setModulesMapName"]),
    ...mapMutations("mapNameSpaced", [SET_MAPNAME]), // 正确写法
    // ...mapMutations("mapNameSpaced", ["SET_MAPNAME"]), // 错误获取写法
  },
};
</script>

<style lang="scss" scoped></style>
// 引入变量名文件
import { SET_MAPNAME } from "../typings";

export default {
  // 强制开启命名空间
  // namespaced: true,
  state: {
    modulesMapName: "state--modules命名空间里的内容",
  },
  getters: {
    getModulesMapName: (state) => state.modulesMapName + "+++getModulesMapName",
  },
  mutations: {
    setModulesMapName(state, payload) {
      state.modulesMapName = payload;
    },
    // 变量名充当函数名
    [SET_MAPNAME](state, payload) {
      state.modulesMapName = payload;
    },
  },
  actions: {},
};
// 可自定义 N 多个操作变量
// ① 多行暴露
// export const SET_MAPNAME = "set_mapName";
// ② 统一暴露
const SET_MAPNAME = "set_mapName";

export { SET_MAPNAME };

如何解决 Vuex 页面刷新数据丢失问题?

1、问题描述:

一般在登录成功的时候需要把 用户信息 ,菜单信息 放置 Vuex 中 ,作为全局的共享数据。

但是在页面刷新的时候 Vuex 里的数据会重新初始化 ,导致数据丢失 。

因为 Vuex 里的数据是保存在运行内存中的 ,当页面刷新时 ,页面会重新加载 Vue 实例 ,

Vuex 里面的数据就会被重新赋值 。


2、解决思路:
办法一:将 Vuex 中的数据直接保存到浏览器缓存中

(sessionStorage、localStorage、cookie)

办法二:在页面刷新的时候再次请求远程数据 ,使之动态更新 Vuex 数据

办法三:在父页面向后台请求远程数据 ,并且在页面刷新前将 Vuex 的数据

先保存至 sessionStorage(以防请求数据量过大页面加载时拿不到返回的数据)

分析:

办法一的缺点是不安全 ,不适用大数据量的存储;

办法二适用于少量的数据 ,并且不会出现网络延迟;

办法三是要讲的重点 ,办法二和办法一 一起使用。


3、使用持久化插件

@2 vuex-persistedstate

原理:

将 Vuex 的 state 存在 localStorage 或 sessionStorage 或 cookie 中一份

刷新页面的一瞬间,Vuex 数据消失 ,Vuex 会去 sessionStorage 中拿回数据 ,

变相的实现了数据刷新不丢失 ~

使用方法:

安装:$  npm install vuex-persistedstate --save 

在 store 下的 index.js 中 ,引入并配置

import createPersistedState from "vuex-persistedstate"
 
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState()]
})

此时可以选择数据存储的位置 ,可以是 localStorage / sessionStorage / cookie ,

此处以存储到 sessionStorage 为例 ,配置如下:

import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({
      storage: window.sessionStorage
  })]
})

存储指定 state:

vuex-persistedstate 默认持久化所有 state ,指定需要持久化的 state , 配置如下:

import createPersistedState from "vuex-persistedstate"
const store = new Vuex.Store({
  // ...
  plugins: [createPersistedState({
      storage: window.sessionStorage,
      reducer(val) {
          return {
          // 只储存state中的user
          user: val.user
        }
     }
  })]

此刻的 val 对应 store / modules 文件夹下几个 js 文件存储的内容 ,

也就是 store / index 中 import 的几个模块 ,可以自己打印看看。

希望哪一部分的数据持久存储 ,将数据的名字在此配置就可以,

目前我只想持久化存储 user 模块的数据 。

注意:如果此刻想配置多个选项,将 plugins 写成一个一维数组,不然会报错。

import createPersistedState from "vuex-persistedstate"
import createLogger from 'vuex/dist/logger'
// 判断环境 vuex 提示生产环境中不使用
const debug = process.env.NODE_ENV !== 'production'
const createPersisted = createPersistedState({
  storage: window.sessionStorage
})
export default new Vuex.Store({
 // ...
  plugins: debug ? [createLogger(), createPersisted] : [createPersisted]
})

@3 vuex-along

将  state  里的数据保存一份到本地存储

( localStorage、sessionStorage、cookie )

// App.vue

<script>
    export default{
        created() {
            //在页面加载时读取sessionStorage里的状态信息
             if (sessionStorage.getItem("store") ) {
                this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
            }
 
            //在页面刷新时将vuex里的信息保存到sessionStorage里
            window.addEventListener("beforeunload",()=>{
                sessionStorage.setItem("store",JSON.stringify(this.$store.state))
            })
        }
    }
</script>

2、使用第三方插件如 vuex-along

( 本质上还是利用 session 等缓存到本地 )

import Vue from 'vue'
import Vuex from 'vuex'
import VueXAlong from 'vuex-along'
Vue.use(Vuex)
let productData = require('@/assets/api/list.json')
 
const moduleA = {
    state: {
        a1: 'a1',
        a2: 'a2',
    }
}
export default new Vuex.Store({
    state: {
        productList: [],//列表数据
        cartList: [],//购物车数据
    },
    mutations: {
        //产品列表
        setProductList(state, data){
            state.productList = data
        },
        //加入购物车
        setCartList(state, id){
            let  cartIndex = state.cartList.findIndex(item => item.id === id)
            if(cartIndex < 0){
                state.cartList.push({id, count: 1})
            }else{
                state.cartList[cartIndex].count++
            }
        },
        //删除购物车商品
        deleteCartList(state, id){
            let  cartIndex = state.cartList.findIndex(item => item.id === id)
            state.cartList.splice(cartIndex, 1)
        },
        //编辑购物车商品数量
        editCartList(state, data){
            let cartIndex = state.cartList.findIndex(item => item.id === data.id)
            state.cartList[cartIndex].count = data.count
        },
        clearCart(state){
            state.cartList = []
        },
    },
    actions: {
        getProductList(context){
            //模拟ajax请求,将返回的信息直接存储在store
            setTimeout(()=>{
                context.commit('setProductList', productData)
            }, 2000)
        },
        buy(context){
            //模拟ajax请求通过返回promise对象将结果返回给操作提交的地方
            return new Promise((resolve, reject) => {
                setTimeout(()=>{
                    context.commit('clearCart')
                    resolve({msg:'下单成功', code: 200})
                    //reject({message: '提交失败', code: 300})
                }, 1000)
            })
        }
    },
    modules: {
        ma: moduleA
    },
    //缓存state的数据到storage
    plugins: [VueXAlong()],
    //全量的参数配置(sessionStorage 数据恢复优先级高于 localStorage)
    /* plugins: [VueXAlong({
        // 设置保存的集合名字,避免同站点下的多项目数据冲突
        name: 'my-app-VueXAlong',
        //过滤ma的数据将其他的数据存入localStorage
        local: {
            list: ['ma'],//需要监听的属性名或者模块名
            isFilter: true,//是否过滤而非保存
        },
        //保存ma的a1数据到sessionStorage
        session: {
            list: ['ma.a1'],
            isFilter: false,
        },
        //仅使用sessionStorage保存
        //justSession: true,
    })] */
})
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值