# ra-page-storage **Repository Path**: rasir/ra-page-storage ## Basic Information - **Project Name**: ra-page-storage - **Description**: 使用sessionStorage和indexdb对当前页签的数据进行缓存,当页面关闭后缓存的数据失效。 - **Primary Language**: TypeScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-08-23 - **Last Updated**: 2023-11-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ra-page-storage [English](./README.en.md) #### 介绍 `page-storage` 使用 `sessionStorage` 和 `indexdb` 对当前页签的数据进行缓存,当页面关闭后缓存的数据失效。 #### 工作原理 1、`page-storage`使用`sessionStorage`缓存当前窗口的`uuid`,当页面刷新时会读取`sessionStorage`中的`uuid`,如果存在则读取缓存数据,不存在则重新生成新的`uuid`。 2、`page-storage` 基于 `indexdb` 封装,使用简单,支持数据缓存,数据删除,数据更新,数据查询等操作,存储在`indexdb`中的`key`为每一个窗口的`uuid`,并且会将`uuid`的数据打上过期时间(`expiredTime`),默认 10s(可以自定义)。 3、`page-storage`使用`web worker`对`indexdb`中数据进行轮询续期,续期周期为过期时间(`expiredTime`)的一半,默认 5s(可以自定义)。 4、`page-storage`还是用了`@rasir/chain-promise-call`方案,让所有操作都工作在链式调用中,保证`indexdb`操作的时续。 5、`page-storage` 所有`api`都支持`promise`操作。 #### 注意事项 1、浏览器兼容性:只要是支持`Promise`的浏览器版本都能兼容。 2、依赖`@rasir/chain-promise-call`。 3、本项目使用的` "core-js": "^3.32.1"`,如果在使用过程中出现兼容问题,请检查`core-js`版本。 4、本文中说是的`链式调用`并不是`jQuery`式的链式调用,而是将所有链式`api`放入一个栈中,当前一个异步函数执行完毕,才会执行下一个函数。保证`indexdb`操作数据存储的时序。 ### 快速使用 `npm i @rasir/page-storage -S` ### 使用方法 1、`html`中直接引用`min.js`。 ```js ``` 2、`npm`使用。 ```js import PageStorage from "@rasir/page-storage"; const storage = new PageStorage({ dbName: "demo_db", sessionWindowKey: "DEMO_KEY", }); storage.chainSavePageStorage({ a: 1, b: 2 }); storage.chainGetPageStorage().then((data) => { console.log(data); }); ``` #### 参数说明 ```js interface IPageStorage { noWindowName?: boolean; // 是否不使用窗口名称作为窗口特征码,默认 false windowName?: string; // 当前窗口的特征码,默认 PAGE_STORAGE windowId?: string; // 当前窗口的uuid expiredTime?: number; // 过期时间,单位秒,默认 10s dbName: string; // indexdb中的storeName 必传 sessionWindowKey: string; // 在 sessionStorage 中保存 windowId 的 key 必传 } ``` #### APIs | API | 说明 | 参数类型 | | ------------------------ | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | | `getPageStorage` | 获取当前窗口数据 | `(): Promise` | | `savePageStorage` | 保存当前窗口数据 | `(data: T): Promise` | | `updatePageStorage` | 直接修改当前窗口的数据 | `(callback: (data?: T) => T \| Promise): Promise;` | | `removePageStorage` | 删除当前窗口的数据 | `(): Promise;` | | `dispose` | 停止给数据续期 | `(): Promise;` | | `chainGetPageStorage` | 加入链式调用的获取当前窗口数据 | `(): Promise` | | `chainSavePageStorage` | 加入链式调用的保存当前窗口数据 | `(data: T): Promise;` | | `chainUpdatePageStorage` | 加入链式调用的直接修改当前窗口的数据 | `(callback: (data?: T) => T \| Promise): Promise;` | | `chainRemovePageStorage` | 加入链式调用的删除当前窗口的数据 | `(): Promise;` | | `chainDispose` | 加入链式调用的停止给数据续期 | `(): Promise;` | | `chainPromiseCall` | 链式调用函数,可以使用`chainPromiseCall.onStatusChange`和`chainPromiseCall.offStatusChange`对实例状态进行监听 | 详见[@rasir/chain-promise-call](https://gitee.com/rasir/chain-promise-call) | #### 问题和解决方案 - 问题:当使用 `window.open` `从一个页面打开一个新的页面时,sessionStorage` 中的数据会被复制到新的页面。这样会导致我们使用 `sessionWindowKey` 来作为每个页面独立存储的设计失效。 - 解决方案: 1. 使用`window.name` 来给当前页面打标签,因为刷新页面时 `window.name` 不会重置。因此在构造函数中,我添加了 `windowName` 属性,用来判断当前页面是否是新开的。如果页面新开,并且不带 `windowName` 的特征码,就清除 `sessionStorage` 中的 `sessionWindowKey` ,并给 `window.name`设置带特征码的 `name`。当然,如果你不想我的 `window.name` 扰乱了的设计,你可以设置 `noWindowName` 属性,这样你需要自己来保证 `sessionStorage` 的唯一性。 2. 抛弃使用原生的 `window.open` 函数。可以用 `` 标签来进行跳转,或者用模拟 `` 标签点击跳转,如下面这样: ```js let link = document.createElement("a"); link.href = "http://example.com"; link.target = "_blank"; link.click(); ```