构建 HTML5 应用程序

使用 HTML5 窗体改进 Web 窗体

Brandon Satrom

下载代码示例

如果您是一名 Web 开发人员,则您以前可能创建过 HTML 窗体。事实上,您可能已创建了众多 HTML 窗体,只是不记得具体的数目了。毫无疑问,您熟悉典型的输入类型,例如文本、密码、文件、隐藏、复选框、单选、提交和按钮,并且您可能在不同时间使用过其中大多数或所有类型。

如果问您最常使用上面所列类型中的哪种输入类型,您可能会像我们中的大多数人一样,说是“文本”。文本输入类型是典型 HTML 窗体开发的多用工具。一方面,它适用于您为其指定的几乎所有作业,但另一方面,它在语义上是中性的,因此在将此元素转化为实际内容时浏览器无法提供任何帮助。为弥补这种不足,开发人员和设计人员已将自己的语义添加到这些元素中(通过 ID 和类名称),并依靠服务器框架和 JavaScript 来处理验证过程和添加丰富的交互内容。

一个典型示例是收集文本字段中的日期。在大多数时候,您希望使用某种日期选取器来增强日期字段的功能。通常可使用手动 JavaScript 或 jQuery UI 之类的框架完成此操作,该框架会添加一种交互行为,从而允许用户从小组件中选择日期并将该日期填充到原始字段中。

与此模式同样有用的是(我们作为开发人员对此类模式已经非常熟悉),它被过于频繁地重复使用,以致于您禁不住要问,“为什么浏览器不能执行此操作?”

值得高兴的是,使用 HTML5 窗体,浏览器可以并且会执行此操作。除了我们已使用多年的文本和少数现有类型外,HTML5 还为输入类型属性添加了 13 个新值,以及众多将加快窗体开发速度的其他属性。本月,我将分享 HTML5 窗体附带的其中一些新输入类型和属性,及其在不同浏览器中的实现状态。接下来,我将简单介绍 HTML5 窗体的新客户端验证功能。最后,我将介绍 Visual Studio 2010 和 Microsoft .NET Framework 4 的最新更新如何使 HTML5 窗体和 ASP.NET Web 窗体很好地协同工作。我将在整篇文章中讨论您目前如何在您的应用程序中使用 HTML5 窗体,同时为旧版浏览器提供后备解决方案。本文中的所有演示(可在线获取)都是使用 Microsoft 免费提供的轻型 Web 开发工具 WebMatrix 构建的。您可以访问 aka.ms/webm,亲自试用 WebMatrix。

HTML5 中的新输入类型

如今我们知道,HTML5 窗体或 HTML5 Web 窗体是以 Web Forms 2.0 作为起点的,后者是由 Web Hypertext Applications Technology Working Group(Web 超文本应用技术工作组,WHATWG)编写的预 HTML5 规范。WHATWG 最初开展的大部分工作已成为我们现在的 HTML5 规范的起点,并且 Web Forms 2.0 的工作成果现在已成为 HTML5 正式规范的一部分,可访问 bit.ly/njrWvZ 以了解相关信息。该规范的很大一部分专门论述输入元素的新类型和内容属性,可在 bit.ly/pEdWFs 中找到相关内容。

正如我提到的,该规范引入了用于窗体的 13 种新输入类型:搜索、电话、url、电子邮件、日期时间、日期、月份、星期、时间、本地日期时间、数值、范围、颜色。

可以轻松地使用这些新类型。例如,我要将一个新电子邮件字段放置在订单窗体中。如图 1 所示,我已使用一些附加字段(包括电子邮件)修改了 WebMatrix Bakery 模板网站的“订单”页。

A Sample Order Form图 1 订单窗体示例

在此窗体中,电子邮件字段带有如下标记:

<input type="email" id="orderEmail" />

请注意,type 属性等于“email”而不是“text”。新 HTML 输入类型最值得称道之处在于,您可以立即使用它们并且它们在某种程度上适用于每个单独浏览器。 当浏览器遇到其中一种新类型时,将出现以下两种情况之一。

如果浏览器不支持新输入类型,将无法识别类型声明。 在这种情况下,浏览器将平稳降级并将该元素视为 type=“text”。您可以通过将该元素放置在窗体中并在 Internet Explorer 9 F12 工具控制台中键入“document.getElementById(‘orderEmail’).type”来尝试一下。 现在,您可以使用这些新类型,并且如果浏览器不支持指定字段,它将继续工作,就像普通文本字段一样。

但是,如果浏览器能够识别某种类型,那么,您可以通过使用它来获得一些直接的好处。 对于已识别类型,浏览器会添加一些特定于类型的内置行为。 对于电子邮件类型,Internet Explorer 10 Platform Preview 2 (PP2) 及更高版本将自动验证任何输入,并在提供的值不是有效的电子邮件地址时向用户显示错误消息,如图 2 所示。

Automatic Browser Validation of the Email Input Type
图 2 电子邮件输入类型的自动浏览器验证

通过每个元素的类型可以轻松推断出该元素的用途和行为,因此,我们可以在窗体中轻松获得另一级别的丰富语义内容。 此外,其中一些新输入类型允许浏览器立即向用户提供更丰富的交互内容。 例如,如果我在某窗体中放置以下元素,然后在完全支持日期输入类型的浏览器中打开该窗体,默认交互形式将比普通的旧文本框更加丰富:

<input type="date" id="deliveryDate" />

图 3 显示可在 Opera 11.5 中提供的日期类型。 最值得称道之处在于,要获得此交互,我只需指定 type=“date”,浏览器即会处理我以前在 JavaScript 中为提供此级别的功能而必须执行的所有手动操作。

The Date Input Type in Opera 11.5
图 3 Opera 11.5 中的日期输入类型

值得注意的是,HTML5 规范并不规定浏览器应如何显示这些新输入类型,或者浏览器应如何显示验证错误,因此,您有望看到浏览器之间的细微乃至重大的差别。 例如,Chrome 13 显示日期的微调控件而不是日期选取器,如图 4 所示(当然,在您看到这篇文章时,浏览器的行为可能已经发生了变化)。 您应该也知道,万维网联盟 (W3C) 正在围绕浏览器样式以及日期时间、日期和颜色等元素的本地化进行讨论。 目前,浏览器尚未就如何实现这些类型达成一致,并且现有实现中 没有任何类似于 jQuery UI 所具备的现行自定义机制。 如果您选择实现或尝试这些新类型,请始终确保提供完善的后备解决方案。 此外,如果表示和行为的一致性对您的用户而言很重要,您可能需要应用自定义样式,重写这些控件上的默认行为或使用基于脚本的解决方案。

The Date Input Type in Chrome 13
图 4 Chrome 13 中的日期输入类型

之前我说过这些字段仍具有普通文本字段的行为,这是浏览器为我们提供的一种最佳平稳降级方式。 但作为纯文本框实现的日期字段并不灵活,并且人们普遍认为该字段提供的用户体验欠佳。 但在 Modernizr 和 jQuery UI 的一些帮助下,您可以提供一个将 HTML5 窗体的最大优势与最佳后备解决方案相结合的解决方案。

在我的上一篇文章 (msdn.microsoft.com/magazine/hh394148) 中提到过 Modernizr (modernizr.com) 是一个 JavaScript 库,可帮助您检测浏览器中是否支持 HTML5 功能。 在本例中,我想使用 Modernizr 来帮助检测是否支持 HTML5 日期输入类型,如果不支持,我将使用 jQuery UI (jqueryui.com) 日期选取器小组件来提供类似的用户体验。 为 Modernizr、jQuery 和 jQuery UI 下载并添加引用后,我可以为我的日期元素添加后备支持,并且只需编写几行代码:

if (!Modernizr.inputtypes.date) {
  $("input[type=date]").datepicker();
}

Internet Explorer 10 PP2 中显示的结果如图 5 中所示。

Date Field Support with jQuery UI
图 5 通过 jQuery UI 实现的日期字段支持

HTML5 中的新输入内容属性

除了新输入类型以外,HTML5 还提供了一些方便的新内容属性,这些属性可在输入字段中用于提供验证支持和增强功能。 其中一个新属性是“placeholder”,根据规范,它“……表示旨在帮助用户输入数据的简短 提示(一个单词或短语)”(强调其作用)。 例如,我可以从我们的订单窗体中获取几个字段并向每个字段中添加 placeholder= =“一些文本”,结果如图 6 所示:

<input type="email" id="orderEmail" placeholder="ex.
name@domain.com" />
<input type="url" id="orderWebsite" placeholder="ex.
http://www.domain.com" />

Using the Placeholder Attribute with Input Fields
图 6 对输入字段使用 Placeholder 属性

占位符文本的颜色比普通文本的颜色浅,如果我将焦点放在每个字段上,该文本将消失,从而使我能够输入自己的值。

与新输入类型一样,占位符属性在旧版浏览器中不受支持。 但用户使用它们访问页面时不会发生不好的情况,因此,可立即考虑使用它们,即使您不打算为旧版浏览器提供相应支持也是如此。 如果确实需要提供“填充代码”占位符支持,Modernizr 可以帮助您。 正如我在上篇文章中所提到的,Modernizr 的忠诚用户尝试保存一个您可能要用于指定 HTML5 功能的每个填充代码和后备支持的运行列表。 可在 bit.ly/nZW85d 中查看该列表。

在本例中,我们使用由 Mike Taylor 创建的 jQuery HTML5 占位符,可从 bit.ly/pp9V4s 上下载它。 获得该占位符之后,将以下内容添加到您的页面所引用的脚本块中:

Modernizr.load({
    test: Modernizr.input.placeholder,
    nope: "../js/html5placeholder.jquery.min.js",
    callback: function() {
      $('input[placeholder]').placeholder();
    }
  });

在此处,Modernizr 会测试占位符属性是否受支持,如果不受支持,将加载 html5placeholder.jquery.min.js。 jQuery 然后会选择具有占位符属性的每个元素并向每个元素添加插件支持。 如果您在 Internet Explorer 9 中尝试此操作,将会发现最终结果看起来非常类似于 Internet Explorer 10 PP2 中提供的本机浏览器支持。

另一个引入注目的新属性是“autofocus”,正如其名字,它用于指定单个窗体字段以便在加载页面时自动接收焦点。 每个页面只能有一个字段保留此属性;如果使用 autofocus 标记多个元素,则具有此声明的第一个元素将在加载页面时接收焦点。 在我的订单窗体中,我希望“名称”字段接收焦点,因此我添加了如下属性:

<input type="text" class="field" id="orderName" autofocus />

autofocus 属性可用于任何窗体控件,是许多 Web 开发人员过去遵循的基于脚本且聚焦窗体的策略的最佳备选属性。

HTML5 窗体验证

在此我没有足够的篇幅介绍引人注目且与窗体相关的所有新属性,但我会花一些时间来介绍“required”、“pattern”、“novalidate”和“formnovalidate”,所有这些属性使客户端窗体验证易如反掌。

对于支持“required”属性的浏览器,该属性将告知浏览器在没有值的情况下无法提交该窗体。 例如,我将“required”添加到我的订单窗体的“名称”字段中:

<input type="text" class="field" id="orderName" required />

当我在 Internet Explorer 10 PP2 中访问此页面并尝试提交窗体时,我看到图 7 中所示的内容。 使用单个属性,浏览器就完全可以使用红色边框设置元素样式,并向用户显示一则消息,指示该字段是必需字段。

Using the Required Attribute on a Form Field
图 7 在窗体字段中使用 Required 属性

前面的 图 2 指示浏览器如何在用户不输入其他内容的情况下自动验证某些类型,例如“电子邮件”和“url”。 使用“pattern”属性,您可以为输入类型提供您自己的验证测试。 根据 HTML5 规范,“pattern”需要一个正则表达式,浏览器会使用该表达式验证自己的字段。

我的订单窗体包含一个电话 (type=“tel”) 字段,并且我可以指定如下验证模式:

<input type="tel" id="orderTelephone" pattern="\(\d\d\d\) \d\d\d\-\d\d\d\d" title="(xxx) xxx-xxxx" />

这个不太复杂的正则表达式会告知浏览器需要一个七位数,并且需要在区号两边添加括号并在本地号码中使用破折号。 输入任何其他数字将会生成如图 8 所示的消息。 请注意,此消息包含有关用户如何设置输入格式的说明:“(xxx) xxx-xxxx”。这部分消息获取自同一元素的 title 属性,因此可以通过您的标记至少控制部分验证消息。 但使用 title 帮助验证时需要注意一点。 根据规范,浏览器可以选择在其他非错误情况下显示 title,因此请不要期望将此属性作为可能出现错误文本的位置。

Using the Pattern Attribute to Specify a Validation Expression
图 8 使用 Pattern 属性指定验证表达式

浏览器自动执行验证很好,但这会产生两个直接的问题。 首先,如何对待通过我的服务器框架(如 ASP.NET MVC)生成的服务器验证或客户端验证脚本? 其次,如果我希望用户无需验证即可将窗体保存为正在进行的工作,又该如何呢? 遗憾的是,第一个问题不在本文讨论范围内,但我曾在 ASP.NET MVC 中写了一篇关于此特定主题的博客文章,您可以在 bit.ly/HTML5FormsAndMVC 中找到它。

第二个问题则很简单。 我们假设您有一个窗体,用户需要花费较长的时间进行提交,甚至可能需要保存多次才能最终将其发布到您的服务器上。 在此类情况下,您希望允许用户提交窗体而无需验证,您可以使用以下两个属性:放置在类型“submit”的输入字段中的“formnovalidate”,以及放置在窗体开始标记上的“novalidate”。 在此,我将在我的窗体上放置两个 submit 字段,如下所示:

<input type="submit" value="Place Order" />
<input type="submit" formnovalidate value="Save for Later" id="saveForLater" />

第二个按钮上的“formnovalidate”属性将关闭验证并提交该窗体,从而允许将用户正在进行的工作保存到我的数据库中,甚至保存到采用新 HTML5 存储技术(如 localStorage 或 IndexedDB)的客户端上。

HTML5 窗体和 ASP.NET Web 窗体

在结束这篇文章之前,我想与 ASP.NET Web 窗体开发人员分享一些与 HTML5 窗体相关的其他信息。 如果您打算使用 ASP.NET Web 窗体进行 HTML5 窗体开发,有一个好消息:.NET 和 Visual Studio 的许多 HTML5 相关更新正在带外发布,因此,您不必等待下一个框架版本即可立即使用这些功能。

若要开始使用 HTML5 窗体和 ASP.NET Web 窗体,您需要获取几个更新。 首先,确保具有 Visual Studio 2010 SP1 (bit.ly/nQzsld)。 除了为新 HTML5 输入类型和属性提供支持外,该 Service Pack 还提供了一些更新,使您能够在 TextBox 服务器控件上使用新的 HTML5 输入类型。 如果没有此更新,您会在使用新类型时看到编译时错误。

您还需要获取 Microsoft .NET Framework 4 Reliability Update 1 (bit.ly/qOG7Ni)。 该更新旨在解决与在 ASP.NET Web 窗体中使用新的 HTML5 输入类型相关的少数问题。 Scott Hunter 在 8 月初发布的一篇博客文章中介绍了其中一些内容(UpdatePanel、验证控件和回调),可访问 bit.ly/qE7jLz 了解相关信息。

向支持 HTML5 的浏览器中添加 Web 窗体支持对各地的 Web 开发人员而言都是一个好消息。 我们不但具有一组在我们的应用程序中使用的语义输入类型,而且现在我们还可在旧版浏览器中使用这些输入类型且无不良影响,同时还可在新版本中获得增强的功能(包括自动客户端验证)。 立即使用这些新字段也可以在移动应用领域带来直接的好处,即,使用“url”和“电子邮件”等类型时将提示移动设备向用户显示针对该输入类型进行优化的软键盘选项。 当您将这些新功能与 Modernizr 及某个最佳代码填充选项结合使用时,您将立刻获得在您的应用程序中采用 HTML5 窗体所需的全部工具。

有关 Internet Explorer 10 PP2 中的 HTML5 窗体支持的详细信息,请访问 ietestdrive.com,并确保查看 Internet Explorer 开发人员中心中的开发人员指南 (bit.ly/r5xKhN)。 通常,若要深入研究 HTML5 窗体,建议阅读“A Form of Madness”,该文章出自 Mark Pilgrim 撰写的“HTML5: Up and Running”一书(O’Reilly Media,2010 年),以及 W3C HTML5 规范 (bit.ly/nIKxfE) 中的“窗体”一节。

Brandon Satrom 是德克萨斯州奥斯汀市以外地区的 Microsoft 开发推广人员。 他的博客地址为 userinexperience.com,还可以通过 Twitter 地址 @BrandonSatrom 与他取得联系。

衷心感谢以下技术专家对本文的审阅: *Jon BoxJohn HrvatinScott Hunter 和 *Clark Sell