[译] 离线友好的表单

本文讲的是[译] 离线友好的表单,


网络不佳时网页表单的表现通常并不理想。如果你试图在离线状态下提交表单,那就很可能丢失刚刚填好的数据。下面就看看我们是如何修复这个问题的。

太长,勿点:这里是本文的 CodePen Demo

随着 Service Workers 的推行,现在开发者们甚至可以实现离线版的网页了。静态资源的缓存相对容易,而像表单这样需要服务器交互的情况就很难优化了。即使这样,提供一些有用的离线回退方案还是有可能的。

首先,我们为离线友好的表单创建一个新的类。接着我们保存一些 <form> 元素的属性然后绑定一个触发 submit 事件的函数:

class OfflineForm {
  // 配置实例。
  constructor(form) {
    this.id = form.id;
    this.action = form.action;
    this.data = {};

    form.addEventListener('submit', e => this.handleSubmit(e));
  }
}

在 submit 处理函数中,我们使用 navigator.onLine 属性内置一个简单的网络检查器。浏览器对它的支持很好,而且实现它也不难。

️ 但它还是有一定误报的可能,因为这个属性只能检查客户端是否连接到网络,而不能检测实际的网络连通性。另一方面,一个 false 值意味着“离线”是相对确定的。因此,比起其他方式这个判断方法是最好的。

如果一个用户当前处于离线状态,我们就暂停表单的提交,把数据存储在本地。

handleSubmit(e) {
  e.preventDefault();
  // 解析表单输入,存储到对象中
  this.getFormData();

  if (!navigator.onLine) {
    // 用户离线,在设备中存储数据
    this.storeData();
  } else {
    // 用户在线,通过 ajax 发送数据
    this.sendData();
  }
}

存储表单数据

存储数据到用户设备有几种不同的方式。根据数据的不同,如果你不希望本地副本持久存储在内存中,可以使用 sessionStorage。在我们的例子中,我们可以一起使用 localStorage

我们可以给表单数据附上时间戳,把它赋值给一个新的对象,并且使用localStorage.setItem 保存。这个方法接受两个参数:key(表单 id)和 value(数据的 JSON 串)。

storeData() {
  // 检测 localStorage 是否可用
  if (typeof Storage !== 'undefined') {
    const entry = {
      time: new Date().getTime(),
      data: this.data,
    };
    // 把数据存储为 JSON 串
    localStorage.setItem(this.id, JSON.stringify(entry));
    return true;
  }
  return false;
}

提示:你可以在 Chrome 的开发者工具 “Application” 中查看存储数据。如果不出差错,你可以看到内容如下:



通知用户发生了什么也是个好主意,这样他们会知道他们的数据不会丢失。我们可以扩展handleSubmit 函数来显示某些反馈信息。



多么周到的表单!

检查保存的数据

一旦用户联网,我们想检查一下是否有被存储的提交。我们可以监听 online 事件来捕获网络链接的改变,还有页面刷新时的 load 事件:

constructor(form){
  ...
  window.addEventListener('online', () => this.checkStorage());
  window.addEventListener('load', () => this.checkStorage());
}
checkStorage() {
  if (typeof Storage !== 'undefined') {
    // 检测我们是否在 localStorage 之中存储了数据
    const item = localStorage.getItem(this.id);
    const entry = item && JSON.parse(item);

    if (entry) {
      // 舍弃超过一天的提交。 (可选)
      const now = new Date().getTime();
      const day = 24 * 60 * 60 * 1000;
      if (now - day > entry.time) {
        localStorage.removeItem(this.id);
        return;
      }

      // 我们已经验证了表单数据,尝试提交它
      this.data = entry.data;
      this.sendData();
    }
  }
}

一旦我们成功提交了表单,那最后一步就是移除 localStorage 中的数据,来避免重复提交。假设是一个 ajax 表单,我们可以在服务器响应成功的回调里做这件事。很简单,这里我们可以使用 storage 对象的 removeItem() 方法。

sendData() {
  // 向服务器发送 ajax 请求
  axios.post(this.action, this.data)
    .then((response) => {
      if (response.status === 200) {
        // 成功时移除存储的数据
        localStorage.removeItem(this.id);
      }
    })
    .catch((error) => {
      console.warn(error);
    });
}

如果你不想使用 ajax 提交,另一个方案是将存储的数据回填到表单,然后调用form.submit() 或让用户自己点击提交按钮。

️ 注意:简单起见,我在这个案例中省略了一些其他部分,比如表单验证和安全 token 验证等,这些东西在真正的生产环境是必不可少的。这里的另一个问题是处理敏感数据,就是说你不能在本地存储一些密码或者信用卡数据等私密信息。

如果你感兴趣,请查阅 CodePen 上的全部示例





原文发布时间为:2017年9月19日


本文来自合作伙伴掘金,了解相关信息可以关注掘金网站。

时间: 2024-09-08 05:55:25

[译] 离线友好的表单的相关文章

10个不错的CSS3表单教程

CSS3的出现,为制作更好的网页表单带来无数新的可能.在本文中,我收集了10种运用新技术CSS3,制作非常棒的表单的教程.HTML5 和 CSS3表单 HTML5引进了类似诸如滑动条.数字旋转器.日期选择自定义这些实用的新表单元素.该教程会教你怎样用HTML制作表单,并且和CSS3相得益彰.它能够将CSS3和HTML5巧妙地结合在一起. 2. 无图片和JavaScript的 CSS3 表单 虽然这个教程是法语的,但是效果出人意料.对于不会法语的读者,只需要找到源代码,并充分利用它. 3. 使用

[译]更好的表单设计: 每一页,一件事(实例研究)

本文讲的是[译]更好的表单设计: 每一页,一件事(实例研究), 原文地址:Better Form Design: One Thing Per Page (Case Study) 原文作者:Adam Silver 译文出自:掘金翻译计划 译者:horizon13th 校对者:LeviDing, laiyun90 更好的表单设计: 每一页,一件事(实例研究) 2008 年,我在 Boots.com 工作时,团队提出需求,要设计当时最流行的单页表单进行付款操作,主要技术有折叠选项卡,AJAX,客户端验

[译] 『小键盘』难题:用户在手机上填写表单吗?

本文讲的是[译] 『小键盘』难题:用户在手机上填写表单吗?, 原文地址:The Tiny Keyboard Problem: Do People Complete Forms on Their Phones? 原文作者:Priceonomics Data Studio 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m- 译者:Changkun Ou 校对者:ylq167 『小键盘』难题:用户在手机上填写表单吗? 本文系根据 JotForm (一家 Priceon

extjs4-Extjs4.1可编辑的grid如何对输入数据进行验证?就像Form表单vtype那种验证。

问题描述 Extjs4.1可编辑的grid如何对输入数据进行验证?就像Form表单vtype那种验证. 使用的是CellEditing插件, 可编辑的grid在编辑的时候,通常希望能够对用户的输入进行控制而不是任由用户随心所欲的输入,如果输入非法内容则给予友好提示,这个怎么实现?

Web注册表单设计样式的研究(上)

如果你想最大化你的服务所带来的效益,你就必须最大化你网站表单的成功率.仅仅简单的让用户在你网站上注册是不够的,除非你有能够让访问你网站的人一看就映像深刻的点子.为了让服务达到最大化的体现,我们设计师需要提供用户一个良好的用户体验.我们需要邀请用户,为他们描述服务产品有多少好,给他们解释为什么他们需要填那些表单并且暗示他们会因此得到利益的回报.当然,我们也应该做的非常方便让用户来参与. 但是设计有效的页面表单不是件容易的事情.有个不争的事实就是:没人喜欢填表单--无论是线上还是线下的.因此,作为设

网页注册表单设计原则

如果你想最大化你的服务所带来的效益,你就必须最大化你网站表单的成功率.仅仅简单的让用户在你网站上注册是不够的,除非你有能够让访问你网站的人一看就映像深刻的点子.为了让服务达到最大化的体现,我们设计师需要提供用户一个良好的用户体验.我们需要邀请用户,为他们描述服务产品有多少好,给他们解释为什么他们需要填那些表单并且暗示他们会因此得到利益的回报.当然,我们也应该做的非常方便让用户来参与. 但是设计有效的页面表单不是件容易的事情.有个不争的事实就是:没人喜欢填表单--无论是线上还是线下的.因此,作为设

HTML 5之表单新功能解析

时光车轮滚滚碾来,前端之路永无止歇.对于这个前端这门精一多专的技术,任何一次技术革新,我们都必须第一时间去了解它学习它,比如Web世界里这簇美艳的花朵---HTML 5.虽然HTML 5发布之初,许多人(包括我)都觉得普及它还很遥远,但自发布以来,许多企业级网站对它的尝试应用(比如<!doctype html>应用,比如canvas的应用),使HTML 5的迈出了一大步,随之而来IE9的发布,无疑又让我们看到了HTML 5离我们不再遥远. 51CTO推荐专题:HTML 5 下一代Web开发标准

HTML5跨浏览器前端表单验证

表单验证是广大前端非常头疼的一项事务,特别是在面对复杂表单的情况下,例如某些输入框仅接受数字输入,某些字段是必填,有些项又必须满足一定输入规则--为了提供更好的用户体验,这些繁琐的需求不得不去花大量时间和代码去满足.在新的 HTML5 标准中,增加了十几个表单输入类型和特性,例如 autofocus 自动焦点,以及之前介绍过的 Placeholder 占位符.这些贴心的特性支持大大解放了前端开发人员,我们仅需使用新的标签元素或属性,就可以完成过去需要大量 javascript 代码才能完成的功能

移动应用表单设计秘籍:提升表单设计的体验

文章描述:本文将从清晰的视觉纵线.信息的分组.极致的减法.利用选择代替输入.标签及文字的排布方式.依靠明文确认密码.合理的键盘利用.校验的小秘密这八个维度来分享我的移动应用表单设计秘籍. 一直想写一篇文章,关于移动应用表单设计的,可惜最近项目很忙,忙到没有时间打理博客.最近体验产品的时候,经常看到错误的的表单设计,要么信息混乱,要么步骤繁复.要么语言程序化,要么视觉焦点跳跃,要么校验顺序混乱,要么反馈不及时,如此种种的问题,让我很想认真的总结一下,思考一下,为移动应用的表单设计,提供一些个人力所