4

20190320233353.png

浏览器内置模块 kv-storage 异步版的 localStorage

LocalStorage 大家都不陌生基本上每天都在跟他打交道。但这是个会阻塞主线程的同步 API,很多情况下存取大量数据可能会造成性能问题。🙁

为了解决这个问题,我们可能会使用 IndexedDB,但后者难以操作,虽然目前有第三方模块可以很轻松操作 IndexedDB,但仍然不是最好的解决方案。

有没有一种既能够像 LocalStorage 一样简单的 API,又能够拥有 IndexedDB 这样的异步存取数据的能力的前端存储解决方案呢❓

这个时候 Chrome 开发团队目前正在测试一款名为 std:kv-storage浏览器内置模块 📦

啥是内置模块?

内置模块 Built-in modules 跟 JS 模块一样,只不过他并不用从远端下载下来使用,而是与浏览器绑定在一起的。

当然,这种内置模块与传统的 web API 最大的不同之处就是需要使用 esm 语法进行导入 ⬇️,这种模块并不会暴露在全局作用域中,你没办法直接通过 window.xxx 来引用,而是需要先 import

在 chrome 中内置模块的标识符是 std:

kv-storage

kv-storage 模块在 API 上与 LocalStorage 类似。常用的方法有:

  • get() 读取数据
  • set() 写入数据
  • delete() 删除数据
  • clear() 清空数据

所有的上述方法都会返回一个 Promise 对象,也就是说这些都是异步的 🏃

20190320222926.png

官网规范:https://wicg.github.io/kv-sto...

不说那么多,先来看看这个内置模块到底怎么用:

环境配置

首先我们需要一个 74 版本以上的 Chrome 浏览器,并且需要打开 chrome://flags/#enable-experimental-web-platform-features

20190320223227.png

浏览器需要支持 modules 在 Chrome 中,要求版本在 61 以上

20190320223446.png

编写演示代码

首先这里用一个 index.html 文件配合 vscode 的 Live Server 做演示

我们要做的一个简单的功能是创建一个表单,用户填写表单过程中,点击保存按钮,填写在表单内的数据都会存储在 kv-storage 中,即便用户不小心刷新了浏览器,点击恢复按钮即可恢复数据。

首先我们需要一个表单:

<form action="">
    <input type="text" name="username" placeholder="username">
    <input type="text" name="message" placeholder="message">
    <button type="submit">保存</button>
    <button type="reset">恢复</button>
</form>

然后定义一个 type 为 module 的 script 标签

<script type="module"></script>

script 标签内就是我们的主要逻辑:

<script type="module">
    import { storage } from 'std:kv-storage' // 首先导入内置模块 kv-storage

    {
        (async () => {
            // 定义两个事件处理函数
            document.querySelector('form').addEventListener('submit', handleClickSubmit)
            document.querySelector('form').addEventListener('reset', handleClickRestore)

            // 当点击保存
            async function handleClickSubmit(e) {
                e.preventDefault()
                let inputs = document.querySelector('form').querySelectorAll('input')
                let kvData = Array.from(inputs).map(item => ({ name: item.getAttribute('name'), value: item.value }))

                await storage.set('formData', kvData) // 获取表单数据并保存在在 key 为 formData 的 store 中
            }

            // 恢复数据事件处理函数
            async function handleClickRestore(e) {
                let formData = await storage.get('formData') // 读取 formData 数据

                document.querySelector('form').querySelectorAll('input')

                formData.forEach(data => {
                    let { name, value } = data
                    document.querySelector(`input[name=${name}]`).value = value // 将数据注入 input 元素内
                })
            }
        })()
    }
</script>

以上,非常简单的一个 DEMO,我们来看看效果:

输入数据并点击保存:

20190320225831.png

我们去 indexdDB 中查看数据是否保存成功:

20190320225927.png

默认在 kv-storage:default 数据库的 store 集合中出现一条 formData 数据,值就是表单数据数组

然后我们刷新浏览器并点击恢复,kv-storage 从 indexedDB 中又读取了数据并注入到表单中

即便是关闭浏览器重新打开依然能够恢复数据

主要的使用方法大概就是这样,目前位置该内置模块仍然在测试中。

兼容

官方给了一套兼容性解决方案,针对检测是否存在该内置模块的 import map 方法;还有针对是否支持 modules 的 nomodules 方案。

检测是否存在内置模块

新增标签设置 type 为 importmap 创建 importmap,当使用 import 方法引入模块的时候,按照路径首先检查是否能够通过 import {storage} from 'std:kv-storage' 引入,如果不可以,则尝试使用 polyfill import {storage} from '/path/to/kv-storage-polyfill.mjs

<!-- The import map is inlined into your page -->
<script type="importmap">
{
  "imports": {
    "/path/to/kv-storage-polyfill.mjs": [
      "std:kv-storage",
      "/path/to/kv-storage-polyfill.mjs"
    ]
  }
}
</script>

<!-- Then any module scripts with import statements use the above map -->
<script type="module">
  import {storage} from '/path/to/kv-storage-polyfill.mjs';

  // Use `storage` ...
</script>
相关文档见:https://github.com/WICG/impor...

检测是否支持 modules

<!-- 支持 ES Modules 的浏览器加载 main.mjs -->
<script type="module" src="main.mjs"></script>

<!-- 旧浏览器不支持 ES Modules 会加载该文件,同时支持 ES Modules 会忽略这个文件 -->
<script nomodule src="main.es5.js"></script>
这里附上 polyfill:https://github.com/GoogleChro...

Chrome 发布的 kv-storage 并不是说有多么的强大,毕竟现在 LocalForage(https://localforage.docschina... 也已经在业内很频繁在用了。作为第一个内置模块,虽现在不建议在生产模式中使用,但足以遇见在不久的将来这中内置模块的方式可能成为一种趋势。

参考:


JS菌
6.4k 声望2k 粉丝