为什么是 HTML5?为什么不呢?UI/UX 与存储挑战 (第 1 部分)
创建一个简单的应用程序(< 50 行代码),
- 下载源代码 - 1.9 KB
- 在浏览器中查看此演示 (并获取源代码):https://codepen.io/raddevus/pen/WNZZRRR^
引言
我写这篇文章是为了引发一场关于现代应用程序开发的对话。
什么是现代应用程序开发?
这实际上是一个古老的梦想:
引用一次编写,随处运行的应用程序。
我知道在某些方面,相信这是可能的有些荒谬,但考虑到“消费者”互联网已经存在 30 年了,并且仍然如此困难,这也同样荒谬。
背景
最近,我想要一个能够执行以下操作的应用程序:
- 允许我保存图像目录 (截图等)
- 图像目录易于更新,我可以非常快速/轻松地添加新图像 (稍后将详细介绍)。
- 可以从我的任何计算机或设备访问 (运行 Linux 的桌面、运行 Win10 的笔记本电脑、iPad (iOS)、Mac Mini (macOS)、Amazon Fire (Android)、运行 Android 的手机等)。
如何被推向特定的技术
我的几乎每台设备都运行不同的操作系统 (Linux、Windows、iOS、macOS、Android)。这立即排除了任何桌面或原生 (移动 Android 或 iOS) 开发的可能——除非我想重复工作。
当然,所有这些设备都具备 Web 访问功能,所以这立即将您推向设计某种 Web 应用程序。
HTML5 可以 (几乎) 解决整个问题 (创建整个解决方案)
HTML5 标准包括 HTML、CSS 和 JavaScript。
这意味着它包含了我们能够创建用户界面 (HTML 控件 - 按钮、下拉列表、编辑框等) 所需的一切。
当然,它包含了 CSS,所以我们可以对其进行样式设置,使其看起来美观,并帮助用户理解用户界面试图帮助用户做什么。
大多数其他功能都可以通过 JavaScript 来完成 (无论您多么讨厌它)。
HTML5 无法真正解决的问题 (几乎解决)
但是,由于浏览器会保护用户,我们没有很好的方法来保存用户数据。纯 JavaScript API 不提供写入用户存储设备的文件或数据的方法。(是的,有 NodeJS API 允许这样做,但纯 JavaScript 不行。)
本文将涵盖哪些内容?
本文将设置基础应用程序,旨在表明我们可以仅使用 HTML5 技术来满足原始要求中的所有三个要求 (位于本文顶部)。但是,我们将再次看到数据存储的局限性。
现在就开始编写代码吧。
如果您想先尝试一下,可以前往 CodePen 查看:https://codepen.io/raddevus/pen/WNZZRRR^ 或下载源代码进行尝试。
首先,用户界面
主界面我只需要一种方式让用户包含图像存储位置的链接。
它只是一个简单的 HTML input type text 和一个用户点击以添加图像的按钮。
就是这样!
现在用户可以粘贴图像链接并点击按钮,它将被添加到我们的应用程序中。
好了,我们需要编写一些代码来处理所有这些。
我希望应用程序做什么
我希望应用程序
- 提供我添加的每个图像的缩略图视图
- 当用户点击图像时,在新窗口 (标签页) 中打开并显示全尺寸图像
- 此外,我还会做一些悬停样式,当用户将鼠标悬停在某个特定图像上时,它会显示一个微妙的边框,以表明用户正在进行某项操作,并且该图像是可点击的。
添加四个图像后,我的初步设想看起来是这样的:
我们需要在代码中构建哪些东西?
- 编写代码以处理添加图像 URL。
- 编写代码以显示用户添加的所有图像的缩略图。
注意:处理无效输入
本文中,我将把处理无效输入 (图像 URL 文本框中没有文本等) 的工作留给读者自行练习。
如果用户在没有 URL 的情况下点击按钮,一个 image 标签将被添加到 DOM 中,但链接将无效,并显示一个损坏的图像标签。我们可能会讨论如何从 localStorage
中删除图像,但目前我不会在此讨论。
这是允许用户添加图像的代码:
function addImage(){
let allImages = JSON.parse(localStorage.getItem("allImg"));
if (allImages === null){
allImages = [];
}
let localUrl = document.querySelector("#imageUrl").value;
allImages.push(localUrl);
localStorage.setItem("allImg",JSON.stringify(allImages));
document.querySelector("#imageUrl").value = "";
removeMainDiv();
displayImages();
}
代码解释
我们首先尝试从用户的浏览器 localStorage
中检索一个名为 allImg
的项。
我们期望它是一个字符串数组 (URL),所以我们将其包装在 JSON.parse()
调用中,它将 localStorage
数据解析为一个对象——在本例中是一个数组。如果我们不 parse()
数据,那么它将只是一个数据字符串。
如果 allImg
项在用户的 localStorage
中不存在,它将返回 null
。
如果 allImages
变量是 null
,那么我们将其初始化为一个空数组。
接下来,我们获取用户在 URL textbox
中输入的新值。
let localUrl = document.querySelector("#imageUrl").value;
接下来,我们将新的图像 URL 推送到图像数组中 (该数组之前是空的,或者包含已存储在 localStorage
中的图像)。
在我们继续讨论这段代码的作用之前,让我们花点时间多谈谈浏览器 API localStorage
。
关于 localStorage
基本上,它是一种基于键值对的浏览器存储。键和值都存储为 string
。
您可以简单地提供一个 string
名称和任何值并进行存储。您的数据也将存储为 string
,因此您需要将其转换为预期的类型。
localStorage
绑定到网站的 TLD (顶级域名)。在一个域上存储的值对任何其他域都完全不可访问。
这意味着如果您在 https:///
处存储了任何内容,那么您将无法从 http://<anyOtherDomain>
检索这些值。
数据也存储在每个浏览器实例中。这意味着在同一台桌面用户的帐户下,但使用不同的浏览器,您将无法访问相同的数据,即使您使用的是同一个域。
例如,如果您使用 Google Chrome 浏览器在 http://mySite.com 上将数据保存到 localStorage
,然后使用您的 FireFox 浏览器访问同一网站,则无法访问该数据。即使是同一个桌面用户也是如此。
数据访问
存储在 localStorage
中的数据只能在初始保存它的同一个浏览器、同一个域上检索。
这是一个安全功能,但同时也使得共享数据或使用户的数据在任何地方都能通过您的单页应用程序访问变得困难。
这对我们的应用程序意味着什么
这意味着,只要您 (和您的用户) 都意识到这个限制,那么编写一个简单的应用程序可能是有效的,该应用程序要求用户始终使用同一台设备上的同一浏览器来检索其数据。
然而,这是一个令人沮丧的限制,必须克服才能使我们的图像目录能够在我们的多个设备上使用。
本地运行应用程序
通过本地运行代码,可以提供一个小型实用程序应用程序。
例如,请按照以下步骤操作:
- 获取源代码 (本文顶部),并将其保存到一个目录中。
- 双击 index.htm。
- 添加图像 URL。
您添加的任何图像都将被添加到您浏览器的 localStorage
中,下次您从该文件夹双击 index.htm 时,它们将被重新加载。这是我在 Brave 浏览器中从文件位置运行的示例:
localStorage 中的所有数据都是字符串
继续解释我们的代码,您现在会看到,当我存储 JavaScript 字符串数组时,我实际上调用了 JSON.stringify()
对数组进行操作,使其变成一个纯 string
。由于存储在 localStorage
中的所有内容都是 string
,这有助于正确处理转义字符等。
由于我们将新的图像 URL 推送到了我们的数组中,它将显示在我们 URL 列表的最后。
这也意味着我们拥有完整的列表 (任何先前加载的以及我们的新列表),可以保存到 localStorage
。然后我们调用将数组转换为 string
,然后将其包装在保存数据到 localStorage
的调用中。
localStorage.setItem("allImg",JSON.stringify(allImages));
这确保了下次页面刷新 (或用户访问网站) 时,所有图像都将存储在 localStorage
中,并可以重新加载和显示。
使用浏览器控制台检查 localStorage
如果您加载了我们的应用程序,然后打开浏览器的控制台窗口 (大多数浏览器中按 F12),您就可以检查 localStorage
。
打开控制台后,只需键入:localStorage.getItem("allImg")
,然后按 Enter。
如果您添加了任何图像,您将看到一个 URL 列表。这是我的样子 (我部分模糊了最后一个,因为它是一个指向某些专有源代码的链接)。
您可以看到它是一个字符串化的数组,因为它外面有包裹数组括号 [ ]
的单引号。
其余代码做了什么?
其余代码只是
- 遍历
localStorage
中的所有图像 - 为每个图像创建一个新的
link
标签 (使其可点击) - 为每个图像创建一个新的
img
标签 - 将
img
标签的src
值设置为在localStorage
中找到的 URL
所有这些工作都显示了缩略图,并使其可点击,以便它们在新窗口中以原始大小打开。
总结 / 前瞻 / RFC
所有这些都是为了开启关于两个主要观点的对话:
- HTML 可以使构建用户界面变得非常容易——动态视图的代码量非常少。
- 使用 HTML5 技术存储用户数据以便于检索要困难得多。
存储此简单用户数据的其他方法
接下来,我将提供存储用户数据的各种想法,我希望听到读者关于他们发现的内容。
在下一篇文章中,我将介绍一些将数据发布到存储数据的远程服务器的简单方法。
征求意见
您发现哪些有用的方法可以做到这一点?
过去,我使用过 Google Firebase,但那里存在一些限制和挑战。
梦想
一个远程持久存储,允许我通过 WebAPI 发布数据,并使用一个秘密/强密钥检索它。数据将使用 AES256 加密。用户所要做的就是调用一个 API,数据就会被存储。
我有一个关于这个的想法,并将在未来的文章中进行介绍。
历史
- 2021 年 12 月 27 日:首次发布