KV 存储的发布对 Web 平台来说是一个大问题,它是 Standard Library Proposal的一部分,它可能会为 JavaScript 引入更广泛的标准库。
在谈到什么是kv存储
之前,让我们先讨论如何在浏览器中存储数据. 如果我现在想存储一些本地数据,我的主要选项之一将是使用 localStorage。
考虑到这一点,让我们用JavaScript创建一个简单的Todo应用程序,利用localStorage,我们需要两个文件:index.html和main.js:
1[label main.js]
2const TODOS_KEY = 'todos';
3const ul = document.getElementsByTagName('ul')[0];
4
5const showExistingTodos = todos => {
6 if (todos.length > 0) {
7 todos.map(todo => {
8 addLi(todo);
9 });
10 }
11};
12
13const addTodo = () => {
14 const input = document.getElementById('todoInput').value;
15
16 if (input.length > 0) {
17 addLi(input);
18 saveTodo(input);
19
20 document.getElementById('todoInput').value = '';
21 }
22};
23
24const addLi = text => {
25 const li = document.createElement('li');
26
27 li.appendChild(document.createTextNode(text));
28
29 ul.appendChild(li);
30};
31
32const saveTodo = todo => {
33 let loadedTodos = loadTodos();
34
35 loadedTodos = [...loadedTodos, todo];
36
37 localStorage.setItem(TODOS_KEY, JSON.stringify(loadedTodos));
38};
39
40const loadTodos = () => {
41 const todos = JSON.parse(localStorage.getItem(TODOS_KEY));
42
43 return todos != null ? todos : [];
44};
45
46const clearTodos = () => {
47 localStorage.removeItem(TODOS_KEY);
48
49 const todos = Array.from(document.getElementsByTagName('li'));
50
51 todos.map(todo => ul.removeChild(todo));
52};
53
54const todos = loadTodos();
55
56showExistingTodos(todos);
1[label index.html]
2<!DOCTYPE html>
3<html lang="en">
4<head>
5 <meta charset="UTF-8">
6 <meta name="viewport" content="width=device-width, initial-scale=1.0">
7 <meta http-equiv="X-UA-Compatible" content="ie=edge">
8 <title>Document</title>
9</head>
10<body>
11 <div>
12 <input id="todoInput" type="text" />
13 <button onclick="addTodo()">Add Todo</button>
14 <button onclick="clearTodos()">Clear todos</button>
15 </div>
16
17 <ul>
18
19 </ul>
20
21 <script src="main.js"></script>
22</body>
23</html>
虽然这绝对可以改进,但我们现在有一个应用程序,我们可以用作例子. 如果我们尝试添加一些Todo项目,然后刷新页面,我们会看到它们立即出现!
Hmm...我做了一些研究,发现‘localStorage’是同步的,这对我们的应用意味着什么?
基本上,这意味着调用LocalStorage
将阻止 DOM 内部的渲染,如果我们在LocalStorage
中有大量元素,这可能会产生问题,并且会显著影响性能。
让我们来看看一个名为 KV 存储的实验内置模块(用于密钥/值存储)。
为什么不使用IndexedDB本地?
使用 KV 存储为我们提供了更直观的 API,类似于localStorage
。我们也不需要转向第三方 IndexedDB 库,我们现在可以直接从浏览器中使用它!
KV 存储
对于这个例子,我们需要在Chrome中启用实验功能,然后在Chrome浏览器中导航到以下地址:
<$>[注] 在实验网页平台功能上选择启用
: chrome://flags/#enable-experimental-web-platform-features。
使用 Chrome Canary用于任何实验或新 Web 功能也是一个好主意。
现在我们将需要执行以下更新:
在index.html
中,导入main.js
作为模块:
1<script type="module" src="main.js"></script>
接下来,我们可以更新我们的saveTodo
函数以使用storage.set()
而不是localStorage.setItem()
。
1const saveTodo = async todo => {
2 let loadedTodos = await loadTodos();
3
4 loadedTodos = [...loadedTodos, todo];
5
6 await storage.set(TODOS_KEY, loadedTodos);
7};
我们的loadTodos
函数使用storage.get()
而不是localStorage.getItem()
:
1const loadTodos = async () => {
2 const todos = await storage.get(TODOS_KEY);
3
4 return todos != null ? todos : [];
5};
<$>[注]请注意,我们如何轻松地使用 async/await 函数来处理非同步性。
最后,我们可以通过使用storage.delete()
而不是localStorage.removeItem()
来改进我们的clearTodos
函数:
1const clearTodos = () => {
2 storage.delete(TODOS_KEY);
3
4 const todos = Array.from(document.getElementsByTagName('li'));
5
6 todos.map(todo => ul.removeChild(todo));
7};
我们还需要将这些暴露在窗口
对象中:
1window.addTodo = addTodo;
2window.clearTodos = clearTodos;
我们的应用程序现在再次工作,但而不是LocalStorage
,它使用了std:kv-storage
内置的Web模块。
这意味着一切都是无同步的(正如我们的无同步
和等待
承诺呼叫所指)。
客户支持
如果浏览器不支持‘kv-storage’? 此时此刻,这是非常有可能的。 幸运的是,这里有一个可用的 polyfill: https://github.com/GoogleChromeLabs/kv-storage-polyfill.
我建议您将其添加到您的应用程序中,如果您计划在这个阶段在生产中使用kv存储
。
进一步阅读
谷歌已经准备了一个演示文稿,你可能会发现有趣的阅读. 这里是URL: https://rollup-built-in-modules.glitch.me/