【源码阅读】vuex-persistedstate
前言
为什么要读vuex-persistedState源码呢?在项目开发中有一些数据需要在登录后全局很多地方使用,但是vuex一刷新数据就没了,要解决刷新后数据持久化问题,就想到了本地存储localStorage,但是在使用本地存储获取数据的过程中,使用computed方法获取数据会存在数据不具备响应效果,数据没及时更新为最新数据操作还比较繁琐,而vuex-persistedState库使用了vuex的方式存储和使用,并解决了数据响应和刷新存在的问题,使用非常方便,就想了解下如何和vuex结合实现的?
源码阅读
了解依赖作用
- 一个库中所需要的所有包和相关依赖都可以在package.json文件中看到,接下来了解下相关包的作用
"dependencies": {
// 对象数组合并更新,支持深度合并和覆盖
"deepmerge": "^4.2.2",
// 工具函数库用于访问、设置和删除JavaScript对象属性的实用方法,支持字符串路径来访问嵌套属性
"shvl": "^2.0.3"
},
"devDependencies": {
// 同babel-core库
"@babel/core": "^7.12.10",
// 根据指定的目标环境,自动确定需要转换的JavaScript语法和特性,并使用相应的插件进行转换,以便在不同环境中运行
"@babel/preset-env": "^7.12.11",
// 自动生成GitHub项目的贡献者列表
"all-contributors-cli": "^6.19.0",
// js编译器,将es6+转换为兼容代码
"babel-core": "^7.0.0-bridge.0",
// jest测试框架中使用babel进行代码转换,以便进行测试和断言
"babel-jest": "^27.0.2",
// 检测和监控构建文件的大小
"bundlesize": "^0.18.1",
// nodejs环境模拟浏览器的本地存储
"dom-storage": "^2.0.2",
// js规范
"eslint": "^8.0.0",
// 管理git钩子,git事件发生时自动触发预定义脚本
"husky": "^7.0.0",
//js 测试框架 单元测试和集成测试
"jest": "^27.0.6",
// 快速构建和发布js库,可将多个模块打包成一个单独的js文件
"microbundle": "^0.14.0",
// 支持同时运行多个npm脚本或命令 如 npm-run-all test:**
"npm-run-all": "^4.1.2",
// 代码格式化工具,自动格式化代码
"prettier": "^2.2.1",
// nodejs模块,用于在Git提交前自动格式化代码,并将格式化后的代码添加到Git暂存区中
"pretty-quick": "^3.1.0",
// node.js模块,用于删除文件和目录
"rimraf": "^3.0.0",
// 基于vue框架
"vue": "^3.0.0",
// 对vuex进行操作的,依赖该库
"vuex": "^4.0.0-rc"
},
// 作用是确保应用程序和依赖的包之间的版本兼容性,以免出现不兼容的情况
"peerDependencies": {
"vuex": "^3.0 || ^4.0.0-rc"
}
探索插件的主要功能和API
-
作用:页面重载之前持久化state中的数据,解决vuex中页面刷新数据不存在问题
-
readme.md一般都会讲述如何使用和功能和api
//下载
npm install --save vuex-persistedstate
// 使用
import { createStore } from "vuex";
import createPersistedState from "vuex-persistedstate";
const store = createStore({
// ...
plugins: [createPersistedState()],
});
- readme.md中的example也提供了参考的例子
了解Vuex的实现原理
- vuex是为vue框架提供的状态管理库
- 其中包含state,mutations,getters,actions,modules,插件等功能
- state是一个响应式对象,存储整个应用程序的状态,并提供统一的访问方式
- getters:计算属性,缓存计算结果,基于state中的数据抽取出的状态
- mutations:同步函数,修改state中的数据
- actions: 异步函数,处理异步逻辑和调用mutations修改state中的数据
- mudules: 允许将state分成多个模块,并可用命名自己的空间,互不干扰
- 插件:可以通过注入插件的方式,调用vuex中的一些公用函数,本仓库就是基于vuex提供的
插件
功能扩展了vuex的数据持久化存储
功能
从入口文件开始阅读
-
package.json了解三个地方:入口、测试、打包
"source": "src/index.ts", // 入口文件路径 "scripts": { "build": "rimraf dist && microbundle --external all --name createPersistedState", // 打包命令 "test": "npm-run-all test:**", // 测试命令 },
-
看入口文件
- 入口文件关键词
source
作用:指定项目源代码文件的位置或路径 - 在
src/index.ts
文件中,可以看出文件中做了两个类型定义(Storage和Options)和提供了一个默认导出的函数,该细节深入在下面的深入关键代码
中探究
- 入口文件关键词
-
了解测试文件
- test.js是该库的测试文件
- 每一条的it就相当于一条测试用例
- 通过描述和执行可以详细了解到相关库的细节和边界
-
打包做了什么
rimraf dist && microbundle --external all --name createPersistedState
移除dist文件夹,并重新打包文件,命名为createPersistedState.js
深入关键代码
从src/index.ts
文件中了解其内部如何实现?
- 从interface接口看配置项有这些属性和方法
- 通过vuex.subscribe方法注册一个回调函数,该函数在每次state发生变化的时候(mutation里面函数触发时)将数据存储到本地,并在每次重载vuex的时候,从本地取数据初始化给state
调试和测试验证代码
以测试为导向的调试也是阅读代码的一种方式,test文件中有许多功能的细节和边界,都值得去看
总结
通过对vuex-persistedstate
库源码的学习,看到了该库实现的原理就是在关键的时刻获取数据和存储数据,比较巧妙的地方在通过插件方式借助了store本身的功能中的subscrible函数,让外部库知道触发state的时机(mutation的时候改变state),在触发的时候保存一下数据到本地,并在fetchBeforeUse的时候获取本地的数据, 并在处理后给store的state。
除此之外,还有一个代码中还有很多函数的使用采用(options.fn || fn)(args)(function (mutation, state){}
这样的方式,也是一个挺值得学习的地方。
转载自:https://juejin.cn/post/7240347693460799543