@h5plus/persist
v0.1.1
Published
基于Vuex的持久化保存,加入了HTML5+ 的 plus.storage 支持
Downloads
5
Maintainers
Readme
persist
基于Vuex的持久化保存,加入了HTML5+ 的 plus.storage 支持
,参考了 vuex-persist
安装
npm install @h5plus/persist --save
# or
yarn add @h5plus/persist
使用
步骤
1.导入
import persist from '@h5plus/persist'
2.创建对象
const vuexLocal = new VuexPersistence({
storage: window.localStorage
})
3.作为 Vuex plugin.
const store = {
state: { ... },
mutations: { ... },
actions: { ... },
plugins: [vuexLocal.plugin]
}
export default vuexStore
构造参数
创建对象时的参数对象 options
| 属性 | 类型 | 说明 |
| --------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| key | string | 在 storage 中存储对应的键值 Default: 'vuex' |
| delKey | string | 需要删除 storage 中存储对应的键值,一般用于换库的时候Default: '' |
| storage | Storage (Web API) | localStorage, sessionStorage, localforage 或自定义的存储对象. 必须有 getItem, setItem, clear 等方法. Default: window.localStorage |
| plus | boolean | 是否 HTML5+ API 中的存储对象(同步存储): plus.storage Default: false |
| needEvent | boolean | 是否需要跨窗体的事件通知 Default: true |
| saveState | function (key, state[, storage]) | 持久化保存 state,可以自定义 |
| restoreState | function (key[, storage]) => state | 从持久化存储中读取 state,可以自定义 |
| reducer | function (state) => object | State reducer. 仅保存需要保存的值。 默认情况下,保存整个 state,如果指定了 modules 则只保存列表中的值;或者自定义 |
| filter | function (mutation) => boolean | Mutation filter. 可以针对 mutation.type
进行过滤 只为那些想要持久化写入的对象触发。 Default 所有的 mutations 返回 true |
| modules | string[] | 要持久化的模块列表。(使用它,你可用不用自定义 reducer) |
| asyncStorage | boolean | 是否异步存储,意味着 store 使用 Promises (例如 localforage) Default: false |
| supportCircular | boolean | 表示该状态是否具有自身的循环引用 (state.x === state) |
使用说明
Reducer
自定义 reducer 不应该改变 state 的结构。
const persist = new VuexPersistence({
reducer: (state) => state.products,
...
})
上面的代码就是错的 wrong 应该这么做:
const persist = new VuexPersistence({
reducer: (state) => ({products: state.products}),
...
})
Circular States
如果你的 state 中有循环引用的结构
let x = { a: 10 }
x.x = x
x.x === x.x.x // true
x.x.x.a === x.x.x.x.a //true
JSON.parse()
and JSON.stringify()
将不能正常工作.
你需要安装 circular-json
npm install circular-json
并且在构造 store 时, 添加 supportCircular
new VuexPersistence({
supportCircular: true,
...
})
示例
简单的
import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersistence from '@h5plus/persist'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
user: { name: 'Arnav' },
navigation: { path: '/home' }
},
plugins: [new VuexPersistence().plugin]
})
export default store
多实例的
示例 1
import Vue from 'vue'
import VuexPersistence from 'vuex-persist'
import Cookies from 'js-cookie'
import { module as userModule } from './user'
import navModule from './navigation'
Vue.use(Vuex)
const vuexCookie = new VuexPersistence({
restoreState: (key, storage) => Cookies.getJSON(key),
saveState: (key, state, storage) =>
Cookies.set(key, state, {
expires: 3
}),
// 只保存 user 模块
modules: ['user'],
// 过滤:只处理类型为 'logIn' 或 'logOut' 的变更
filter: mutation => mutation.type == 'logIn' || mutation.type == 'logOut'
})
const vuexLocal = new VuexPersistence({
storage: window.localStorage,
// 只保存 navigation 模块
reducer: state => ({ navigation: state.navigation }),
// 过滤:只处理类型为 'laddNavItem' 的变更
filter: mutation => mutation.type == 'addNavItem'
})
const store = new Vuex.Store({
modules: {
user: userModule,
navigation: navModule
},
plugins: [vuexCookie.plugin, vuexLocal.plugin]
})
export default store
示例 2
import VuexPersistence from '@h5plus/persist'
import localForage from 'localforage'
const vuexLocal = new VuexPersistence({
// 使用 localForage
storage: localForage,
// 只保存 rates 模块
modules: ['rates'],
// 过滤:只处理类型为 'rateUpsert' 的变更
filter: mutation => {
return mutation.type == 'rateUpsert'
}
})
const baseData = new VuexPersistence({
key: 'base',
// 只保存 'coins', 'config' 模块
modules: ['coins', 'config'],
// 过滤:只处理类型为 'coinsUpsert' 或 'walletUpsert' 的变更
filter: mutation => {
return mutation.type == 'coinsUpsert' || mutation.type == 'walletUpsert'
}
})
const recordsData = new VuexPersistence({
// 使用 plus.storage
plus: true,
key: 'records',
// 只保存 records 模块
modules: ['records'],
// 过滤:只处理类型为 'rateUpsert' 的变更
filter: mutation => {
return mutation.type == 'recordsUpsert'
}
})
const vuexStore = new Vuex.Store({
state,
getters,
mutations,
actions,
plugins: [baseData.plugin, recordsData.plugin, vuexLocal.plugin]
})
export default vuexStore
严格模式
支持 Vuex 严格模式
(注意, 不要在发布环境下启用严格模式!)
在严格模式, 不能使用 store.replaceState
,所以使用一个变更(mutation)来代替
你需要添加 RESTORE_MUTATION
到你的 mutations
看下面示例
配置严格模式支持
import Vue from 'vue'
import Vuex from 'vuex'
import VuexPersistence from 'vuex-persist'
const vuexPersist = new VuexPersistence({
// This **MUST** be set to true
strictMode: true,
storage: localStorage,
reducer: state => ({ dog: state.dog }),
filter: mutation => mutation.type === 'dogBark'
})
const store = new Vuex.Store({
// This makes the Vuex store strict
strict: true,
state: {
user: {
name: 'Arnav'
},
foo: {
bar: 'baz'
}
},
mutations: {
// 这个变更 **必须** 命名为 "RESTORE_MUTATION"
RESTORE_MUTATION: vuexPersist.RESTORE_MUTATION
},
plugins: [vuexPersist.plugin]
})
一些常用的 store
- js-cookie 使用浏览器 Cookie
- window.localStorage (PC 重启也会保留, 知道你清理浏览器数据)
- window.sessionStorage (关闭浏览器选项卡时消失)
- localForage 使用浏览器中的 IndexedDB 数据库
- plus storage Storage 模块管理应用本地数据存储区,用于应用数据的保存和读取
关于 LocalForage 和异步存储的注意事项
HTML5 DOM 规范定义的 Window.Storage API,它实现了以下功能 -
interface Storage {
readonly length: number
clear(): void
getItem(key: string): string | null
key(index: number): string | null
removeItem(key: string): void
setItem(key: string, data: string): void
[key: string]: any
[index: number]: string
}
如您所见,它是一个完全同步的存储。 还要注意它仅保存字符串值。 因此,对象被字符串化并存储。
现在看 Local Forage 代表的接口 -
export interface LocalForage {
getItem<T>(key: string): Promise<T>
setItem<T>(key: string, data: T): Promise<T>
removeItem(key: string): Promise<void>
clear(): Promise<void>
length(): Promise<number>
key(keyIndex: number): Promise<string>
_config?: {
name: string
}
}
你可以在这注意到 2 个不同之处-
- 所有函数都使用 Promises 来进行异步(因为 WebSQL 和 IndexedDB 是异步的)
- 它保存的可以是对象(不仅仅是字符串)
当使用异步(基于 Promise)存储时,您的状态将不会立即从 localForage 恢复到 vuex。它将进入事件循环,并在 JS 线程为空时完成。这可以调用几秒钟的延迟。