npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@h5plus/persist

v0.1.1

Published

基于Vuex的持久化保存,加入了HTML5+ 的 plus.storage 支持

Downloads

5

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 个不同之处-

  1. 所有函数都使用 Promises 来进行异步(因为 WebSQL 和 IndexedDB 是异步的)
  2. 它保存的可以是对象(不仅仅是字符串)

当使用异步(基于 Promise)存储时,您的状态将不会立即从 localForage 恢复到 vuex。它将进入事件循环,并在 JS 线程为空时完成。这可以调用几秒钟的延迟。

参考这个来处理

参考