编写更自主的 JavaScript

Avatar of Matt Holt
Matt Holt 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

以下是来自 SmartyStreets 的 Matt Holt 的客座文章。Matt 告诉我他们开发了一个用于验证地址的新插件,因为他知道我们之前也曾探索过 地址处理技巧。他并非过多地推广他们的产品,而是分享插件开发的理念,但我认为客座文章可以同时做到这两点。他欣然同意了。

街道地址很复杂。它们应该很简单。

它们之所以难是因为

  1. 地址不是单个的数据单元;它包含 2 到 6 个不同的部分
  2. 地址不规则且不可预测(无法用正则表达式匹配)
  3. 地址可能在某种程度上有效,但并非完全有效
  4. 地址通常是结账时客户混淆的来源

在 SmartyStreets,我们通过创建一个基于事件的高度自主的 jQuery 插件来解决这个问题(双关语),该插件连接到权威的地址 API。我们亲切地称之为 jQuery.liveaddress

您可以在此 LiveAddress 文档页面 上看到它的实际效果。

in-action

实际应用可以在 ProCPRTortuga Rum Cakes 和其他结账、注册和联系表单上看到。最终结果让我想要看到更多无需干预或配置即可正常工作的自主 jQuery 插件。

自主的脚本/应用/插件不需要手把手指导。它会自行执行,广播其正在执行的操作,并且“正常工作”。在这里,我将简要介绍自主插件的两个方面

  • 即插即用
  • 基于事件

即插即用

与 Web 应用不同,jQuery 插件需要适应其环境。jQuery 的选择器引擎 Sizzle 消除了很多痛苦,但在我们的例子中,地址不能仅仅被“选择”。它们必须被识别或“映射”。

因此,jQuery.liveaddress 非常特殊:它不仅仅是您可以直接对一组匹配元素调用的函数,也不支持链式调用。为了真正做到即插即用,我们的插件必须自动查找表单中与地址数据相关的元素:街道、城市、州、邮政编码等。插件会扫描您的页面以查找此类元素,并自动将其排列成由表单对象管理的地址结构。所有内容都在内部监控以进行更改。我们称此过程为“自动映射”。

以下是我们旧的 Javascript 实现的初始化方式。它没有自动映射,而且工程设计得不是很好

QadApi({
    timeout: 10,
    key: "HTML-KEY",
    busySubmit: false,
    autoClean: false,
    submitId: "submit",
    allowPost: false,
    properCase: true
    // ... other service-related configuration ...
  },
  {
    busyId: "QadBusy"
    // ... other CSS-related configuration ...
  },
  [
    {
      name: "Javascript Example",
      street: "street",
      city: "city",
      state: "state",
      zip: "zipcode"
    }
    // ... other addresses to be mapped, if any ...
  ]
);

将其与自动映射的 jQuery.liveaddress 进行比较

var liveaddress = $.LiveAddress("YOUR-API-KEY");

看到区别了吗?

在具有清晰输入nameid 属性,甚至<label> 标签和placeholder 属性的网页上,自动映射效果非常好。您不会相信我在测试期间看到的那些外观怪异的表单,其中nameid 与字段本身无关,当然,也没有<label> 标签。(设计师:注意!)对于此类情况,我们确实提供了一种方法,可以在初始化期间或之后使用选择器字符串手动映射字段

liveaddress.mapFields([{
  id: 'billing',                // IDs are not part of the address
  street: '#street1',
  street2: '#street2',
  city: '#city',
  state: '#state',
  zipcode: '#zip'
}]);

请记住,如果您的插件自动执行或假设某些操作,请确保开发人员可以覆盖它并进行控制。

jQuery 插件不应该是您来自宜家的厨房桌子(需要大量组装)。它不能开箱即用吗?无论对您的特定脚本意味着什么,都随它去吧:尽可能不要让我配置它!

基于事件

考虑您可能想要介入地址验证过程中间并执行某些操作的情况。如果未引发任何事件,您如何知道地址刚刚被验证?您必须进入脚本的源代码并在其中找到自己的解决方法。事件是对此的优雅且正确的解决方案。

幸运的是,Javascript 使事件成为一件非常常规的事情!(某种程度上。) 使用事件。在发生有趣(或不有趣)的事情时触发它们。

jQuery 使事件变得轻而易举,甚至会维护对每个绑定处理程序的引用。因此,虽然我们都习惯于使用 jQuery 绑定到事件,但不要忘记也引发它们

$(someElement).trigger(eventName, extraData);   // or use triggerHandler()

引发事件时,请务必传入与事件相关的任何数据,以便处理程序具有状态(上下文)。

jQuery.liveaddress 在其生命周期中最多会引发 14 个自定义事件。正如您将在下面看到的那样,这非常有用且功能强大。

事实上,jQuery.liveaddress 在内部绑定到自己的事件。这意味着您可以随时随地停止该过程。例如,要阻止用户提交缺少辅助(公寓)编号的地址

liveaddress.on("AddressAccepted", function(event, data, previousHandler) {
  
  if (data.response.isMissingSecondary()) {

    data.address.abort(event);      // reset some things internally
    alert("Don't forget your apartment number!");
  
  } else {
                
    previousHandler(event, data);   // continue the process

  }

});

请注意,此on() 函数是在 liveaddress 对象上调用的,而不是 jQuery 通常的on()。当您使用 jQuery 的on() 绑定处理程序时,该处理程序将在之前绑定的处理程序之后触发。由于插件首先绑定到其自己的事件,并且每个处理程序都链接到下一个事件,因此您的处理程序只有在整个过程完成后才会触发。

为了解决这个问题,jQuery.liveaddress 提供的自定义on() 函数将取消根之前的处理程序,放下您的处理程序,然后在其之上放置其他处理程序。这意味着您的处理程序首先触发。如您所见,要继续验证过程,只需调用作为参数传入的先前处理程序即可。如果您想要最终决定权,只需不要调用先前的处理程序即可。

6 个地址字段 1 个地址字段

在结束之前,我们先简单说一下。这是针对设计师的。

如前所述,街道地址很复杂。它们需要 2 到 6 个表单字段,它们的顺序经常不同,每个人填写的方式都不同,并且输入过程中经常出现错误。是的,验证输入很重要,但我不是来推广这一点的。相反,您是否考虑过 将所有字段合并为一个

用户更习惯于以自然或直观的方式输入地址,就像他们在信封上写地址一样。这往往可以减少输入错误并带来愉悦的体验。

虽然 解析地址字符串存在一些注意事项,但这仍然是对访客体验的重大改进。这样,用户可以输入自由格式的地址,如果需要,您可以存储各个组成部分。

结论

我们已经了解了几种使 Javascript 不像高维护女友的方法。结合语义标记,脚本可以更易于使用、更智能、更直观。理想情况下,它们会通过引发事件来广播其操作,以便其他代码可以了解正在发生的事情并挂接到它们。脚本自动化程度越高,它在诸如购物车结账页面或具有高度动态内容和功能的页面等恶劣环境中就必须越健壮。自主脚本在可能的情况下适应其环境,如果无法适应则会优雅地失败。