面向 Asp.NET 开发者的 HTML5 编程教程(一)

随笔4个月前发布 迈克尔
48 0 0

原文:HTML5 Programming for ASP.NET Developers

协议:CC BY-NC-SA 4.0

零、简介

欢迎来到 HTML5 的精彩世界!如果你是一名 ASP.NET 开发者,想用 HTML5 特性增强你的 ASP.NET 应用,那你就选对了书。与它的后继者相比,HTML5 提供了更加丰富和复杂的特性。HTML5 不仅仅是关于额外的标记标签——它是关于可以使用客户端脚本编程的 API。

一方面,HTML5 简化了以前不可能的任务;但与此同时,它要求对 HTML5 的特性以及将这些特性集成到应用中的方法有一个详细的了解。这就是为什么你需要一本专门讨论如何将 HTML5 集成到你的 web 开发框架中的书:《ASP.NET》。当 ASP.NET 最初发布时,核心焦点是服务器端编程。然而,由于 Ajax 的流行,客户端变得越来越丰富。今天开发的大多数专业网站都利用 JavaScript 和 Ajax 的力量来提供更好的用户体验。因为许多 HTML5 特性可以使用 JavaScript 编程,所以在客户端完成的总体工作将继续增加。ASP.NET、JavaScript、Ajax 和 HTML5 听起来像是独立的部分,但实际上它们相互补充,构成了现代 web 应用开发的完整画面。这本书旨在帮助你理解这幅图是什么样子,以及如何在你的 ASP.NET web 应用中挖掘 HTML5 特性的全部潜力。

这本书是给谁的?

这本书是为那些想在现有的或新的 web 应用中开发 HTML5 的 ASP.NET web 开发人员而写的。这本书并没有讲述 ASP.NET 的特征。我假设你已经习惯了和 ASP.NET 一起工作,并且已经习惯了一般的 web 应用开发。

本书中讨论的所有代码示例都使用 C#作为服务器端编程语言。所以,你也应该知道 C#。对于客户端代码,本书使用了 jQuery——一个基于 JavaScript 的库。虽然不需要预先了解 jQuery,但我假设您熟悉 JavaScript 的基础知识。

贯穿全书的例子使用了 SQL Server 和实体框架。虽然你不需要对这些有详细的了解,但是你应该熟悉它们。

最后,本书使用 Visual Studio 作为开发工具。您应该知道如何使用 Visual Studio 来执行基本任务,如创建项目和调试代码。

Web 表单或 MVC

ASP.NET 为开发 web 应用提供了两种选择:ASP.NET Web Forms 和 ASP.NET MVC。无论是开发基于 Web 表单的应用还是基于 MVC 的应用,使用本书中讨论的 HTML5 特性或多或少都是一样的。因此,这本书将代码样本呈现为 Web 表单和 MVC 应用的混合体。如果 HTML5 特性的用法有所不同,这两个选项都包括在内。所有的 MVC 应用都使用 ASPX 视图。

所需软件

为了完成本书中讨论的示例,您需要以下软件:

  • Visual Studio 2012
  • SQL Server 2012
  • 网络浏览器:ie 9、Firefox、Chrome、Opera、Safari

虽然我使用 Visual Studio Professional 2012 来开发本书的示例,但大多数示例也可以使用 Visual Studio Express 2012 for Web 来开发。

所有数据驱动的示例都是使用 SQL Server 2012 Express Edition 开发的。我在很多例子中使用 Northwind 示例数据库,我建议您在自己的终端安装它。您可以从 MSDN 下载网站下载 Northwind 数据库及其脚本。一些例子(尤其是那些需要 Web Socket 协议支持的例子)需要 Windows 8 才能成功运行。

HTML5 是一个不断发展的规范。在撰写本文时,各种浏览器在不同程度上支持 HTML5 特性。在整本书中,我使用不同的浏览器(IE9、Firefox、Chrome、Opera 和 Safari)来说明 HTML5 的特性。当您开发使用 HTML5 特性的 web 应用时,建议您在这些浏览器中测试这些特性。因此,您应该在您的开发机器上安装所有这些浏览器的最新版本。

本书的结构

这本书由 13 章和 1 个附录组成。下面是一个快速概述:

  • Chapter 1 gives you a brief overview of HTML5 features discussed in the book. It also discusses some important features of Visual Studio 2012 from the perspective of HTML5.
  • Many features of html 5 can be programmed with JavaScript. Chapter 2 teaches you the basics of jQuery-a popular JavaScript library. JQuery is used throughout the book. If you are not familiar with jQuery, this chapter will help you get started and run.
  • Since HTML5 provides native support for playing media files, it is now easy to play audio and video files. Chapter 3 introduces these two aspects in detail.
  • Chapter 4 introduces HTML5 canvas, which allows you to draw in the browser window using JavaScript objects.
  • If you use ASP.NET to develop data-driven web applications, Chapter 5 of will certainly attract your attention: it covers new HTML5 input types and enhancements to HTML forms.
  • Chapter 6 discusses historical API and custom data attributes (data-*). History API allows you to programmatically add entries to browser history, and custom data attributes allow you to define metadata for elements.
  • HTML 5 introduces a new type of client storage, called web storage. With web storage, you can store information as key-value pairs. Chapter 7 covers this useful topic. Although most web applications need real-time network connection to run normally, some applications can be developed to work offline. Chapter 8 discusses what is an offline web application and how to develop one.
  • Chapter 9 shows how to use the file API to read the file information and the file content selected by the user. This chapter also teaches you to use HTML5 local drag and drop.
  • Web 工作器 lets you develop web pages so that JavaScript processing can run in the background. In this way, the user interface responds to the user interaction processing logic behind the scenes. Chapter 10 covers this important and useful feature.
  • HTML5 adds a new way of communication between client and server. They include postMessage API, events sent by the server, XMLHttpRequest (level 2) and Web socket. It is the theme of chapter 11 of .
  • With the increasing popularity of mobile devices, customizing your own network applications according to the current location of users is looking for ways to enter handheld devices. Chapter 12 discusses geographic location-let you develop the features of location-aware network applications. Chapter 13 covers some important enhancements of Cascading Style Sheets Version 3 (CSS3). With these functions, you can add fancy decorations to HTML elements, such as web fonts, shadows, transparency, gradients and rounded borders.

附录 A 列出了一些 HTML5 的学习资源。

下载源代码

该书的完整源代码可以在该书的配套网站上下载。访问[www.apress.com](http://www.apress.com),进入本书的信息页面。然后,您可以从源代码/下载部分下载源代码。

联系作者

你可以通过我的网站[www.bipinjoshi.com](http://www.bipinjoshi.com)[www.bipinjoshi.net](http://www.bipinjoshi.net)找到我。你也可以在脸书和 Twitter 等流行的社交网站上关注我(链接见我的网站上的“订阅”部分)。

一、HTML5 和 ASP.NET 4.5 概述

直到最近,ASP.NET 开发人员还不需要太在意 HTML 的版本号——现在突然每个人都在谈论 HTML5 了!这就是 HTML 标准的发展对我们现在和将来开发的网页的影响。当然,传统 HTML(如 HTML 4.01)提供的旧功能不会消失。之前的版本是 HTML5 不可分割的一部分,但 HTML5 提供的新改进对任何 ASP.NET 开发者都有吸引力。

本章给你一个 HTML5 特性的快速概述。它还解释了 HTML5 和 ASP.NET 如何适应 web 应用。对 ASP.NET web stack 的概述和在 Visual Studio 中创建项目的一步一步的讲解可以让您快速掌握 ASP.NET 技巧。

本章具体涵盖:

  • A brief history of html 5
  • HTML5 page layout
  • New tag label
  • HTML5 programmable features
  • The Position and Mode of html 5 Suitable for ASP.NET Application

html 5 的历史

为了理解数字 5 背后的魔力,有必要回顾一下 HTML 标准十多年来的发展历史和背后的灵感。如果你从网络的早期就开始设计网页,你会记得那时,网页基本上是静态 HTML 元素的集合。网页缺乏你今天看到的交互性、响应性和复杂性。旧的 HTML 仅仅是 web 开发人员和设计人员用来创建网页的一组标记标签。它也不关心标记的严格性。

在完成了 HTML 4 的大部分工作后,万维网联盟(W3C)决定为 HTML 标记开发一个标准——XHTML。XHTML 规范为 HTML 标记引入了严格的规则,比如要求开始标记有相应的结束标记,标记要正确嵌套,等等。这些规则是出于好意引入的,受到了开发人员社区的赞赏。然而,很明显,没有人想放弃使用旧 HTML 开发的不符合 XHTML 规则的网页。网页开发者和浏览器公司都没有停止对传统 HTML 标记的支持,转而支持新的 XHTML 标准。结果,网页变成了旧 HTML 和 XHTML 的混合体。人们努力进一步发展 XHTML,但是浏览器和开发人员社区拒绝放弃对普通老式 HTML 标记的支持。XHTML 规则虽然从理论角度来看很好,但不足以让 web 社区放弃对传统 HTML 的支持。

2004 年,一群人,大部分来自浏览器制造公司(如苹果、Mozilla 和 Opera),组成了 Web 超文本应用技术工作组(WHATWG)。新成立的小组开始从不同的角度看待 HTML。他们没有谈论规则、标准和严格性,而是集思广益,讨论如果添加到 HTML 中,将为 web 设计人员和开发人员增加价值的功能。传统的 HTML(正式版 4.01)加上这些附加功能成为了 HTML5。该倡议得到了社区的支持,发展势头良好,并于 2007 年被 W3C 接管进行标准化。2008 年 1 月,W3C 发布了 HTML5 的工作草案。此外,还引入了 XHTML 5(html 5 文档的一组标准);它本质上是对 XHTML 的更新,正和 HTML5 规范一起被定义。

过去的经验表明,抛弃 HTML 并用别的东西取而代之是不可能的。因此,HTML 被认为是当前的标准:虽然它被称为 HTML5 是为了引用它的新功能,但从浏览器和规范的角度来看,它只是 HTML。下一节将在您学习 HTML5 页面的基本布局时阐明这一点。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 虽然 XHTML 永远无法取代 HTML,但它对 web 开发者和设计者产生了积极的影响。由于 XHTML 的严格规则,网页开发人员和设计人员越来越意识到要改进他们网页的结构。web 设计工具也通过突出由不适当的嵌套和缺少结束标签引起的标记级错误而得到改进。

HTML5 页面结构

现在您已经了解了 HTML5 的简史,让我们来看看一个简单的 HTML5 web 页面。打开任何文本编辑器,例如 Windows Notepad、TextPad 或 Visual Studio 的默认文本编辑器,并键入清单 1-1 中显示的标记。

***清单 1-1。*一个简单的 HTML5 页面

`

         
Welcome to HTML5             

Hello HTML5!

   `

将文件另存为Hello.htm,双击它在默认浏览器中打开。图 1-1 显示了Hello.htm在 Internet Explorer 9 (IE9)中的运行示例。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

*图 1-1。Hello.htm*的试运行

虽然构建这个网页不是火箭科学,但它揭示了一些有趣的事情。首先,看看清单 1-1 中的<!DOCTYPE>声明:它告诉你这个文档是一个 HTML 文档。注意在DOCTYPE中没有提到 HTML 版本。这意味着即使将来 HTML 增加了新的特性(毫无疑问会增加),文档仍然是 HTML 文档,而不是 HTML4 或 HTML5 文档。将这个简单的DOCTYPE声明与下面的 HTML5 之前的声明进行比较:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/ xhtml1-transitional.dtd">

复杂的DOCTYPE声明在 HTML5 中被简化为简单的形式。

清单 1-1 包括适当嵌套的标记,如<head><title><h1>。然而,HTML5 和 web 浏览器原谅了大多数嵌套错误,就像旧的 HTML 一样。当然,作为一种良好的实践,您应该遵循格式良好和结构良好的标记的准则。

在前面的例子中,您使用了文本编辑器来创建Hello.htm。作为一名 ASP.NET 开发人员,您可能会使用 Visual Studio 或 Visual Web Developer 来开发您的网页。幸运的是,这些工具理解并支持 HTML5 标记。图 1-2 显示了 Visual Studio 中的选项对话框,在这里可以配置相关的设置。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-2。*Visual Studio 中的选项对话框

当您配置 Visual Studio 使用 HTML5 时(Visual Studio 2012 默认使用 HTML5),您创建的所有 HTML 页面和 Web 表单都使用 HTML5 样式的DOCTYPE声明。清单 1-2 中的标记显示了在 ASP.NET 网站中创建的默认 web 表单标记。

***清单 1-2。*网络表单的默认标记

`<%@ Page Language=“C#” %>

    
         

    

     `

你也可以在 Visual Studio IntelliSense 中看到特定于 HTML5 的标记(图 1-3 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-3。*Visual Studio IntelliSense 中特定于 HTML5 的标签

尽管 HTML5 和 web 浏览器可以原谅大多数标记错误,但是作为一名优秀的开发人员,您应该确保您的 HTML5 页面标记遵循推荐的使用规则。为了帮助完成这项任务,您可以使用 W3C 标记验证服务:一个验证 HTML 和 XHTML 文档的在线工具。图 1-4 显示了以Hello.htm作为输入的该实用程序。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-4。*验证 HTML5 文档

请注意,此工具可能无法正确验证 ASP.NET 服务器端标记。例如,runat="server"属性可能被标记为错误。如果你使用的是 Visual Studio,你的工作会更简单,因为当你键入你的标记时,验证错误会自动突出显示(见图 1-5 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-5。*Visual Studio 中的 HTML5 文档验证

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意你可能想知道为什么在 Visual Studio 中创建的 HTML 页面会将xmlns设置为[www.w3.org/1999/xhtml](http://www.w3.org/1999/xhtml)。此命名空间指示 HTML5 文档正在使用 XHTML5 规范中的验证规则;Visual Studio 编辑器会相应地标记验证错误。

快速浏览 HTML5 专用标签

在开始学习 HTML5 的可编程特性之前,浏览一下一些新添加的元素会很有帮助。表 1-1 列出了一些元素,这些元素不仅可以让你设计出更加结构化的网页,还可以提供 HTML 标记中从未有过的功能。然而,请注意,任何与网页结构良好相关的元素的详细讨论(在表 1-1 的前几行)都超出了本书的范围。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意你可以在[w3schools.com/html5/default.asp](http://w3schools.com/html5/default.asp)找到一个整洁方便的 HTML5 标签引用。

在接下来的章节中,你会遇到表 1-1 中提到的一些元素。必要时会对它们进行解释。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

感兴趣的 HTML5 特性

增强标记只是 HTML5 故事的一小部分。HTML5 不仅仅是标记;它包括一组可以使用客户端脚本编程的特性。

随着时间的推移,web 应用已经超越了静态标记。几乎所有现代 web 应用都使用 JavaScript、jQuery、Ajax、验证、数据访问等技术。为了应对 web 应用不断变化的特性,HTML5 已经朝着正确的方向迈出了一步,为 web 开发人员通常需要的功能提供了本机支持。与其依赖第三方来提供支持或从头开发这样的功能,不如消费 HTML5 提供的原生支持。例如,ASP.NET 开发人员使用验证控件或自定义验证库来验证用户输入。但是 HTML5 本身支持许多通常需要的验证。因此,HTML5 是一把伞,涵盖了标记标签、标记标准、可编程 API 和新的 JavaScript 对象。

本书的后续章节将逐一剖析 HTML5 APIs 和相关的 JavaScript 对象。本节对这些可编程特性的概述让您对未来有所了解。

音频和视频

播放音频和视频文件曾经是一件棘手的事情,通常需要依赖第三方插件,比如 Flash 和 Silverlight。HTML5 引入了<audio><video>元素,因此网页可以轻松播放媒体文件。这种本地支持意味着播放媒体文件不需要特殊的插件、小程序或 ActiveX 控件。HTML5 还提供音频和视频 API 来控制正在播放的音频和视频的各个方面。这种可编程性使您可以更好地控制媒体文件以及如何播放它们。

画布

web 流行的原因之一是提供给最终用户的 GUI:从最终用户的角度来看,图像、动画、字体和其他交互式效果使 Web 站点更具吸引力。然而,web 开发人员在浏览器中绘制图形时经常会遇到限制。开发人员通常使用 Flash 或 Silverlight 插件在服务器端生成图形,然后将它们作为图片发送到客户端浏览器。

HTML5 通过提供<canvas>元素在客户端图形渲染方面做得很好。您使用 canvas API 进行实际的绘制。canvas API 可能有用的一些领域包括图表、游戏和在线绘图工具。

历史 API

在 HTML5 出现之前,web 开发人员很难控制会话历史及其操作。HTML5 历史 API 提供了一种执行任务的方法,例如在会话历史中向前和向后移动、向历史中添加新条目以及当用户在历史中导航时同步页面内容。history API 是一种通过 JavaScript 操作浏览器历史的标准化方法,在 Ajax 驱动的应用中特别有用,因为在给定的时间点,页面 URL 和显示的内容之间没有一对一的映射。

网络存储

作为一名 ASP.NET 开发人员,您可能已经使用 cookies 在客户端存储了少量数据。使用 cookies 的一个限制是可以保存的数据量。例如,许多浏览器将每个 cookie 限制为 4,096 字节。

HTML5 web 存储允许您使用 JavaScript 代码在客户端存储更多数据。Web 存储有两种风格:本地存储和会话存储。本地存储跨浏览器会话保持在客户机上,而会话存储仅针对当前会话保持。这些存储被公开为两个新的 JavaScript 对象:localStoragesessionStorage

离线 Web 应用

通常,web 应用需要与服务器实时连接才能运行。当服务器由于某种原因脱机或网络连接暂时中断时,这种始终连接的行为会产生问题。HTML5 应用缓存特性在离线应用缓存 API 的帮助下解决了这些情况。脱机应用使用缓存清单文件,该文件存储了要在本地缓存的文件列表。典型的缓存清单包括网页、图像、样式表和脚本文件的列表。这样,即使网络连接暂时不可用,也可以访问这些文件。您的应用也可以使用离线应用缓存 API 来处理页面的更新版本。

文件 API

传统上,客户端代码从不访问本地文件系统。但是 HTML5 允许你读取和查找关于本地文件的信息。这种功能允许您在将文件或其数据发送到服务器之前执行自定义处理。HTML5 拖放功能和文件 API 可以结合使用,将文件从本地机器拖到网页上,然后采取进一步的行动(比如,将文件上传到服务器或显示图像文件的缩略图)。

网络工作者

Web 工作器 API 为基于浏览器的应用带来了多线程。Web 工作器 本质上允许您在一个单独的线程中加载和执行 JavaScript 代码,而不会影响用户界面的响应。这意味着最终用户可以继续使用用户界面,而 web 工作人员在后台运行一些处理。当处理完成时,用户会得到通知,或者页面会根据处理结果进行更新。

网络套接字

如果您曾经编写过桌面聊天应用,那么您可能知道套接字编程。套接字本质上是可编程的接口,它们通过网络互相插入。一旦连接上,这两个系统就可以互相通信:客户机对服务器,服务器对客户机。

另一方面,网页是基于请求-响应模型的。当 web 服务器向客户端发送响应时,它不会与客户端保持持续的连接。因此,如果服务器想要通知客户端一些有趣的事情,它没有任何办法这样做。一种流行的解决方法是使用 Ajax 请求定期 ping 服务器。但是这种拉取技术仍然是单向通信,并且由于太多请求的可能性而不总是有效的。

另一方面,WebSocket 提供了一个双向通信通道,让服务器向客户端浏览器发送数据。它们为 web 应用提供了套接字编程能力。

地理位置

地理定位有可能成为 HTML5 的一个流行特性,因为它为 web 应用带来了位置感知。使用地理定位,您可以开发依赖于用户位置的应用(假设运行页面的设备可以报告位置)。例如,一个网站可能向居住在特定地区的人提供折扣率或特价。此外,地理定位在手机和平板电脑等移动设备上也有很大用处。

CSS3

严格来说,CSS3 不是 HTML5 的直接特性,而是随着 HTML5 一起发展的。任何 HTML5 和 ASP.NET 开发者了解 CSS3 都是值得的。ASP.NET 的开发人员非常依赖 CSS 来设计 Web 表单、视图和页面的外观和格式,CSS3 引入了一些很酷的新特性,一定会吸引开发人员的注意。诸如框、阴影、可下载字体、表格布局、过渡和媒体查询等功能特别值得注意,因为它们让开发人员完成了以前不容易完成的事情。

HTML5 和浏览器支持

尽管 HTML5 还不是官方标准,但是您可以在您的 ASP.NET web 应用中开始使用它的许多特性。所有领先的浏览器——Mozilla Firefox、谷歌 Chrome、Opera Software 的 Opera、苹果 Safari 和微软 IE——都在不同程度上支持 HTML5。如今,大多数浏览器频繁发布更新版本,HTML5 支持在每个新版本中都有所改进。就新版本的发布频率而言,IE 稍显落后,但 IE9 确实支持几个 HTML5 特性。

作为一种良好的编程实践,您应该始终在目标浏览器中测试您的 Web 表单、视图和普通 HTML 页面。有两种方法可以检查目标浏览器是否支持特定的 HTML5 功能:

  • Development static state
  • Runtime dynamics
静态检查 HTML5 支持

使用这种方法,您可以手动确保目标浏览器支持网页中使用的功能。您可以从任何在线实用程序获得帮助,这些实用程序会告诉您特定的浏览器版本是否支持某些 HTML5 功能。例如,[html5test.com](http://html5test.com)提供了一种很好的方法来检测浏览器对 HTML5 的支持。图 1-6 显示了 HTML5 测试站点的主页,显示了用于查看站点的浏览器的 HTML5 支持分数。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-6。 [html5test.com](http://html5test.com)浏览器评分

在图 1-6 中可以看到,Windows 7 上的 IE9 在 500 分中得了 138 分。你也可以查看其他浏览器的评分。图 1-7 展示了火狐 11、Chrome 18 和 Opera 12 的功能对比。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-7。*火狐、Chrome 和 Opera 评分对比

与其他浏览器相比,IE9 的得分很低。此外,IE9 只能在 Windows 7 上运行,进一步限制了它的受众。在撰写本文时,Internet Explorer 10 仍处于开发阶段,但其他浏览器在发布新版本或更新方面相当积极。在现实世界中,除了针对单个浏览器,您别无选择,只能针对多个浏览器及其对 HTML5 特性的不同支持。

动态检查 HTML5 支持

只有在您知道目标浏览器的情况下,静态检查 HTML5 特性支持才能正常工作。例如,如果您正在开发一个只供某个特定公司的员工使用的内部网 web 应用,您可以在特定的浏览器上实现标准化,并相应地编写 HTML5 特性。然而,在当今时代,用户可以从许多浏览器和设备访问网站,其中一些只提供特定的浏览器选择,因此依赖这样的浏览器标准化可能不是最好的方法。如果您的 web 应用被广泛使用,那么您不能保证最终用户使用的是哪种浏览器。现实世界 web 应用开发的一个事实是,您需要一种健壮且安全的方法来在运行时检测浏览器对 HTML5 特性的支持。你需要插入代码,在运行时检测浏览器及其 HTML5 支持;然后,根据结果,您的网页应该使用这些功能或使用其他功能。

您可以手动添加执行各种测试的 JavaScript 代码,以检测目标浏览器是否支持特定的 HTML5 功能,但是测试和管理这样的代码太复杂了,因为有太多的东西需要检查。幸运的是,实用程序库可以让您的生活变得简单。其中一个很受欢迎的实用程序库是 Modernizr。Modernizr 是一个开源的 JavaScript 库,可以帮助您构建支持 HTML5 和 CSS3 的网站。要使用 Modernizr 库,您首先需要从[modernizr.com](http://modernizr.com)下载开发版本或生产版本。除非您希望调试脚本,否则建议使用生产版本,因为它的大小很小。您也可以指定要包含在库中的功能测试。下载的 Modernizr 库可用于您的网页中进行特征检测。

为了让您了解如何使用 Modernizr,让我们开发一个简单的网页—HelloModernizr.htm—并测试几个 HTML5 特性。清单 1-3 展示了HelloModernizr.htm的完整 HTML 标记。

***清单 1-3。*使用 Modernizr 检测特征

`

         
Welcome to HTML5                    

Hello HTML5!

      

   `

如您所见,HelloModernizr.htm在 head 部分包含了两个 JavaScript 库。第一个<script>标签引用一个 jQuery 库,另一个引用 Modernizr。<script>块遵循对四个 HTML5 特性的测试:音频、视频、画布和拖放。当页面加载到浏览器中时,功能检测代码运行。注意Modernizr对象的使用,它有各种代表 HTML5 特性的属性。如果浏览器支持某个特定的特性,这个示例页面会向 ID 为Message<div>元素追加一条消息。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意HelloModernizr.htm中使用的 jQuery 代码相当容易理解。当网页在浏览器中完全加载时,ready()事件处理程序运行。要选择具有特定 ID 的 HTML 元素,可以使用#语法。在<div>上调用的append()方法将提供的文本/标记追加到元素中。您将在第二章中更详细地了解 jQuery。

图 1-8 显示了HelloModernizr.htm在 Firefox 中的运行示例。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

**图 1-8。**火狐HelloModernizr.htm的样本运行

注意如何在浏览器上确认对<audio><video><canvas>标签和拖放的支持。

HTML5 和 ASP.NET

您已经了解了 HTML5 的历史及其特性。您还创建了几个简单的 HTML5 页面,并使用 Modernizr 库来检测浏览器对 HTML5 特性的支持。现在,让我们看看 HTML5 如何融入整个 ASP.NET 堆栈。图 1-9 显示了 ASP.NET 技术堆栈。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-9。【ASP.NET 栈

如你所见,ASP.NET 是整体的一部分。NET 框架,并且非常依赖于。NET 框架基础类库。在…的顶端。NET 框架,ASP.NET 提供了专门针对 web 应用的功能和服务。这些功能和服务包括身份验证、授权、成员资格、角色管理和配置文件管理,所有这些都可以在 ASP.NET 网站和服务中使用。构建 ASP.NET 网站的两种主要方式是 web 表单和 MVC 应用。要开发服务,您可以使用 ASMX web 服务(从 ASP.NET 的 1.0 版本开始提供)或其他更好的选项,如 Windows Communication Foundation(WCF)服务和 Web API。

图 1-9 显示 Web 表单和 MVC 视图将使用 HTML5。乍一看,您可能认为 HTML5 的使用仅限于 ASP.NET 应用的显示部分。虽然用户界面是你大量使用 HTML5 的地方,但是集成更深入。图 1-10 显示了 HTML5 和 ASP.NET 之间的集成。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-10。【HTML5 与 ASP.NET 互动

当收到请求时,ASP.NET 服务器端基础结构向浏览器发送 HTML5 标记。ASP.NET 服务器端基础结构由 web 表单代码文件或 MVC 控制器中的代码组成。大多数现实世界的 web 应用使用驻留在数据存储区(如 SQL Server)中的数据。要访问这些业务数据,可以结合使用 ADO.NET 和普通旧 CLR 对象(POCOs)或实体框架。

当 ASP.NET 服务器端基础结构将 HTML5 标记发送到客户端浏览器时,浏览器会呈现用户界面,并允许最终用户使用该页面。前面提到的许多 HTML5 特性公开了可编程的 API,可以使用 JavaScript 代码来使用这些 API。反过来,JavaScript 代码可以与服务器通信,以检索处理所需的数据或配置。例如,假设您让最终用户使用 HTML5 canvas API 在浏览器中绘制一个简单的条形图。完成图表后,您可能希望用户将其数据和相关信息保存到数据库中。这需要将数据从客户端浏览器传输到服务器。为了促进这种数据传输,您可以使用 jQuery 并向一段服务器端代码发送 Ajax 请求。然后,服务器端代码将数据保存到数据库中。

HTML5 的某些特性在页面呈现后可能不需要任何服务器端交互。例如,您可以显示一个使用新的<input>类型的 HTML <form>,比如EmailURL。这样做不需要与服务器进行任何对话。

既然你已经知道了 HTML5 在 ASP.NET 中的位置,那就有必要了解一下 Visual Studio HTML 编辑器的一些特性,它们可以让你的生活变得简单。

Visual Studio HTML 编辑器的功能

Visual Studio HTML 编辑器提供了许多简化网页设计的功能。作为一名 ASP.NET 开发人员,您可能熟悉 HTML 编辑器的许多特性,所以本节不一一讨论;相反,它检查了一些有趣的方面。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意关于 Visual Studio HTML 编辑器的所有可用特性,您可以参考 MSDN 文档。在 MSDN 图书馆中搜索 visual studio html 编辑器应该可以让你入门。

HTML 格式

当您设计 HTML 页面时,格式化各种标记标签使得导航和定位特定元素变得容易。Visual Studio HTML 编辑器在设置标记格式方面做得很好。如果你需要调整默认的格式行为,你可以通过工具>选项对话框;参见图 1-11 。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-11。*改变 HTML 格式选项

例如,使用格式选项,您可以配置是否应该自动添加结束标记,属性值是否应该用双引号括起来,等等。点击标签特定选项按钮打开一个对话框,您可以在其中配置单个标记标签及其设置(图 1-12 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-12。*配置单个标签的格式选项

特定于标记的选项包括大纲规范(是否可以折叠和展开标记,以及实现此行为所需的最少行数)、HTML 编辑器中标记的前景色和背景色、换行符等等。对于大多数标记,Visual Studio 设置的默认值很好。但是,在某些情况下,您可能希望更改默认值。例如,在处理大量使用<audio><video>标签的网站时,您可能需要考虑更改默认标签的前景色和背景色,以使它们更容易定位。

【HTML5 标签的智能感知和验证

Visual Studio HTML 编辑器的一个受开发人员欢迎的功能是智能感知。虽然 IntelliSense 很常用,但有几件事值得注意,因为乍一看它们并不明显。

智能感知列表没有显示所有可能的 HTML 标记。显示哪些标签供您选择取决于您使用的 HTML 验证方案。您可以从选项对话框中配置验证选项,如图图 1-13 所示。

默认情况下,Visual Studio 2012 HTML 编辑器使用 HTML5,并且当发现“显示错误”下列出的任何条件时,也会显示错误。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-13。*配置验证选项

保存配置后,如果试图在网页中输入无效的 HTML 标记,编辑器会将其显示为验证错误。图 1-14 显示了属性值没有用引号括起来时出现的错误信息。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-14。*HTML 编辑器显示的验证错误

另请注意,如果您将验证选项设置为 HTML5 以外的其他选项(比如 HTML 4.01),特定于 HTML5 的标记(如<canvas><audio><video>)将不会出现在 IntelliSense 中。

HTML5 片段

Visual Studio HTML 编辑器的另一个节省时间的功能是 HTML5 片段。HTML5 片段将 HTML5 标记的常用片段添加到您正在编辑的网页中。然后,您可以根据需要定制该片段。图 1-15 显示了智能感知窗口中的 HTML5 音频片段。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-15。*智能感知中的 HTML5 片段

在 IntelliSense 中选择 HTML5 代码片段后,按 Tab 键两次以完全展开代码片段,并将其添加到当前光标位置(图 1-16 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-16。 HTML5 音频剪下按 Tab 键两次后展开

一旦代码片段被添加到编辑器中,您就可以根据需要对其进行修改。

自动重命名结束标签

有时你在网页中输入 HTML 标签时可能会不小心拼错。比如说,你输入的不是<audio>,而是<aidio>。默认情况下,当您关闭一个开始标记时,Visual Studio 会自动添加一个相应的结束标记:标记变成<aidio></aidio>。要更正错误,您不必同时修改开始和结束标记,更正开始标记也会自动修复结束标记。

JavaScript IntelliSense

Visual Studio 不仅为 HTML5 标记提供智能感知,还为 JavaScript 代码提供智能感知。前面,本章介绍了 jQuery 和 Modernizr 库。Visual Studio 也为这些库的对象、方法和属性提供了智能感知。图 1-17 显示了智能感知窗口中列出的 Modernizr 对象的属性。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-17。 JavaScript 智能感知

请注意,要显示如图 1-17 所示的 Modernizr 成员,您必须使用<script>标签引用页面中的 Modernizr 库。

在特定浏览器中测试网页测试

为了确保网页能够在不同的浏览器中正确呈现,您可能需要在不同的浏览器中运行它。图 1-18 显示了 Visual Studio 在这种情况下的一个便利特性。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-18。*在不同的浏览器中运行网页

标准工具栏上的“运行”命令显示一个下拉列表,其中包含计算机上安装的所有浏览器。您可以从列表中选择任何浏览器,Visual Studio 将在选定的浏览器中启动您的 web 应用。

还有一种方法可以同时在多个浏览器中浏览 HTML 文件。如果在解决方案资源管理器中右击任何 HTML 文件并选择浏览菜单选项,会打开一个对话框,如图 1-19 所示。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-19。*选择多个浏览器查看一个 HTML 页面

当您单击“浏览”时,网页将在所有选定的浏览器中启动。

示例 Web 应用

现在,作为一名 ASP.NET 开发人员,你已经对 HTML5 能为你提供什么有了基本的了解,让我们通过开发两个使用 HTML5 特性的简单的 ASP.NET web 应用来结束这一章。第一个 web 应用使用 ASP.NET Web 窗体,第二个使用 ASP.NET MVC。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意在这个阶段,你不需要太担心 jQuery 语法和 HTML5 特性在这些 web 应用中的利用。这些示例旨在让您快速、简单地理解到目前为止所讨论的内容。后面的章节将全面介绍这些主题。

一个简单的基于 ASP.NET 网络表单的网络应用,使用 HTML5

在本节中,您将开发一个基于 ASP.NET Web Forms 的应用,该应用使用 HTML5 <audio><video>标签播放音频和视频文件。要播放的音频和视频文件是在运行时使用 jQuery 代码检索的。

创建 ASP.NET Web 窗体项目

要开始开发应用,请使用 C#作为编码语言,在 Visual Studio 中创建一个新的 ASP.NET web 应用。图 1-20 显示了 Visual Studio 中的新建项目对话框。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-20。*在 Visual Studio 中创建新的 Web 表单项目

在应用中添加三个文件夹:ImagesMediaScripts。这些文件夹分别存储图像、媒体文件(音频/视频)和脚本文件。在Media文件夹中放几个 MP3 音频文件和 MP4 视频文件。也复制一些 jQuery 和 Modernizr 库文件到Scripts文件夹中。图 1-21 显示了设置这些文件夹后的解决方案浏览器。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意如果您还没有下载最新版本的 jQuery 和 Modernizr JavaScript 库,您可以通过访问相应的网站([jquery.com](http://jquery.com)[modernizr.com](http://modernizr.com))来下载。准备好这些文件的副本,因为在本书的例子中会用到它们。您也可以从 Microsoft 内容交付网络(CDN)访问它们;这样,您就不需要维护文件的本地副本。更多详情请访问[www.asp.net/Ajaxlibrary/cdn.ashx](http://www.asp.net/Ajaxlibrary/cdn.ashx)

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-21。*带有脚本、音频和视频文件的解决方案资源管理器

添加母版页和内容页

创建项目后,使用添加新项目对话框向 web 应用添加一个母版页(图 1-22 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-22。*添加母版页

将母版页命名为MasterPage.master,并添加清单 1-4 中所示的标记。

***清单 1-4。*标记来自MasterPage.master

`<%@ Master Language=“C#” AutoEventWireup=“true” CodeBehind=“MasterPage.master.cs”
                      Inherits=“Example_03.MasterPage” %>

  
Welcome to my HTML5 web site!    **  **   

    

      
面向 Asp.NET 开发者的 HTML5 编程教程(一)       

      
HTML5 rocks!
    

  

  

    

                           ` `    

  

`

注意清单 1-4 中显示的标记使用了之前在表 1-1 中提到的几个特定于 HTML5 的标签。还要注意,jQuery 和 modernizrModernizr 脚本文件是在母版页中引用的,因此不是每个内容页面都必须再次引用它们。当您输入标记时,请注意 Visual Studio IntelliSense 如何显示特定于 HTML5 的标记,从而使您的工作变得简单。

现在使用“添加新项目”对话框添加一个带有母版页的新 web 表单,并选择MasterPage.master作为其母版页(图 1-23 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-23。*添加带有母版页的 web 表单

接下来,将清单 1-5 中的标记添加到Default.aspx中。

***清单 1-5。*标记为Default.aspx

`<%@ Page Title=“” Language=“C#” AutoEventWireup=“true” MasterPageFile=“~/MasterPage.Master”
CodeBehind=“Default.aspx.cs” Inherits=“Example_03.Default” %>

<asp:Content ID=“Content1” ContentPlaceHolderID=“ContentPlaceHolder1”
                       runat=“server”>
  


    

Play random Audio and Video files!

  

  


    
    

    

    

    

    

    

    

    

  

</asp:Content>`

清单 1-5 中的标记呈现了两个按钮,一个<audio>标签和一个<video>标签。<audio><video>标签的src属性被设置为默认媒体文件,但稍后您将通过编程方式更改src。这两个按钮调用返回要播放的随机媒体文件的服务器端代码。然后将返回的媒体文件赋给<audio><video>标签的src属性,以便动态设置媒体文件。图 1-24 显示了 IE9 运行时的Default.aspx

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 1-24。IE9 中的Default.aspx

添加 Web 方法

目前,点按“播放随机音频文件”和“播放随机视频文件”按钮不起任何作用。您需要编写服务器端和客户端代码来使它们正常工作。进入Default.aspx的代码隐藏文件,添加两个名为GetAudio()GetVideo()的 web 方法,如清单 1-6 所示。

***清单 1-6。*从客户端调用的 Web 方法

[WebMethod] public static string GetAudio() {     //write logic to return random audio file     return "audio1.mp3"; } [WebMethod] public static string GetVideo() {     //write logic to return random video file     return "video1.mp4"; }

注意,这两个方法都是静态的,并且用[WebMethod]属性修饰。此属性是必需的,这样方法就可以被 web 调用,并且可以从客户端代码中调用。GetAudio()GetVideo()不从一组文件中返回一个随机文件,但是你可以在方法中添加逻辑;目前,它们返回预定义的音频和视频文件名。

编写 jQuery 代码来调用 Web 方法

要从客户端代码调用GetAudio()GetVideo() web 方法,需要在Default.aspx文件中添加一些 jQuery 代码。清单 1-7 显示了代码。

清单 1-7。 jQuery 代码调用GetAudio()GetVideo() Web 方法

`

KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲playaudio”).cli….ajax({**
**        type: “POST”,**
**        url: ‘default.aspx/GetAudio’,**
**        contentType: “application/json; charset=utf-8”,**
**        dataType: “json”,**
**        success: function (results) {**
**          KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲audio”).src = r…(“#audio”).trigger(“play”);**
**        },**
**        error: function (err) {**
**          alert(err.status + ” – ” + err.statusText);**
**        }**
**      })**
    });

KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲playvideo”).cli….ajax({**
**          type: “POST”,**
**          url: ‘default.aspx/GetVideo’,**
**          contentType: “application/json; charset=utf-8”,           dataType: “json”,**
**          success: function (results) {**
**            KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲video”).src = r…(“#video”).trigger(“play”);**
**          },**
**          error: function (err) {**
**            alert(err.status + ” – ” + err.statusText);**
**          }**
**        })**
      });
  });
`

清单 1-7 中的所示的<script>块由四部分组成:

  • HTML document event handler
  • HTML5 audio and video feature detection uses Modernizr
  • Click the playaudio button event handler.
  • Click the playvideo button event handler.

当 HTML DOM 树完全加载到浏览器中时,执行ready()事件处理程序。它首先使用 Modernizr 的audiovideo属性检查浏览器是否支持 HTML5 音频和视频特性(参见粗体标记的代码)。如果浏览器不支持音频或视频,则会向用户显示一条错误消息。

接下来连接playaudio按钮的 click 事件处理程序。它使用 jQuery $.ajax()调用GetAudio()(参见事件处理程序中的粗体代码)。当GetAudio()返回一个音频文件时,<audio>元素的src属性被设置为返回的文件名,并触发其play()方法播放音频文件。注意如何使用results.d语法访问GetAudio()的返回值。如果调用GetAudio()时出现错误,将显示一条错误消息。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意web 应用也使用 CSS 文件来处理 web 表单的外观。您可以从第一章代码下载中获得该项目的完整源代码,包括 CSS 文件。

一个简单的基于 ASP.NET MVC 的网站,使用 HTML5

在本节中,您将开发一个显示 HTML5 画布的 ASP.NET MVC 应用。您可以在画布上绘制一个字符串,然后将该字符串发送到服务器以保存在数据存储中。

创建 ASP.NET MVC 项目

首先在 Visual Studio 中创建一个 ASP.NET MVC 项目(图 1-25 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-25。*创建新的 ASP.NET MVC 项目

确保您选择了一个空的项目模板,并以 ASPX 作为视图引擎(图 1-26 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-26。*选择 ASPX 视图引擎。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意尽管您在本节中构建的 web 应用不依赖于特定版本的 MVC,但是这里显示的屏幕截图假设您已经选择了 MVC4 项目模板。

与您之前创建的 ASP.NET Web Forms 项目不同,MVC 项目已经包含一个添加了 jQuery 和 Modernizr 库的Scripts文件夹。当然,如果您热衷于使用这些库的最新(或某些特定)版本,您可以像以前一样将它们添加到Scripts文件夹中。图 1-27 显示了新创建的 MVC 项目的文件夹结构和脚本文件。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-27。*ASP.NET MVC 项目的文件夹结构和脚本文件

添加控制器和动作方法

右击Controllers文件夹,从菜单中选择添加控制器,添加一个名为HomeController ( 图 1-28 )的新控制器。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-28。*添加HomeController

HomeController类添加两个名为Index()SaveCanvas()的动作方法,如清单 1-8 所示。

*清单 1-8。HomeController*的行动方法

`public ActionResult Index()
{
    return View();
}

public JsonResult SaveCanvas(string data)
{
    //add code to store canvas data in some database
    Session[“canvas_data”] = data;
    return Json(“Canvas data stored successfully!”);
}`

Index() action 方法只是返回您马上创建的索引视图。从客户端 jQuery 代码调用SaveCanvas()方法。SaveCanvas()的返回类型是一个JsonResult对象,它代表了。NET 数据类型。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意 JSON 是一种轻量级的数据交换格式。这是一种基于文本的格式,基于 JavaScript 编程语言的子集。由于其基于文本的特性,它很容易生成、读取、写入和解析。

为了简单起见,SaveCanvas()不执行任何数据库操作,但是如果您希望将数据持久化到数据库中,您可以添加这些操作。代码将数据存储在名为canvas_data的会话变量中。通过使用Json()方法将成功消息包装成 JSON 格式,将其返回给调用者。

添加视图

接下来,右键单击Index()动作方法,并从快捷菜单中选择添加视图。添加一个名为 Index 的新 ASPX 视图(图 1-29 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-29。*添加索引视图

将清单 1-9 中的标记添加到位于Views/Home文件夹中的索引视图中。

***清单 1-9。*索引视图的标记

`<%@ Page Language=“C#” Inherits=“System.Web.Mvc.ViewPage” %>

` `     
Index    **  
Enter Text : ** **  

关于这个标记,有几件事情需要注意。首先,它使用 HTML5 <canvas>标签并定义一个 500 像素宽、200 像素高的画布。其次,它使用session变量canvas_data来填充TextBox,因此TextBox包含canvas_data的值。

编写 jQuery 代码来调用操作方法

现在您需要为 Draw 和 Save 按钮连接事件处理程序。您可以使用 jQuery 代码来实现,如清单 1-10 中的所示。

清单 1-10。 jQuery 代码在画布上绘制并保存会话数据

`

$(“#Button2”).click(function () {
      var data = ‘{ “data” : “’ + KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲Text1”).val() +….ajax({**
**        type: “POST”,         url: ‘/home/SaveCanvas’,**
**        data: data,**
**        contentType: “application/json; charset=utf-8”,**
**        dataType: “json”,**
**        success: function (result) {**
**          alert(result);**
**        },**
**        error: function (err) {**
**          alert(err.status + ” – ” + err.statusText);**
**        }**
**      })**
    });
  });
`

这段 jQuery 代码首先使用 Modernizr 库检查浏览器是否支持 HTML5 画布。然后它为Button1(绘制)和Button2(保存)连接 click 事件处理程序。请注意粗体代码。第一个片段基本上掌握了Canvas对象及其绘图上下文。然后设置绘图上下文的几个属性,如fillStylefontfillRect()方法绘制画布背景。方法在指定的 x 和 y 位置绘制提供的文本。要绘制的字符串取自TextBox,文本对齐设置为居中。

Button2的 click 事件处理程序使用$.ajax()并向SaveCanvas()动作方法发送一个POST请求。然后将从SaveCanvas()返回的消息显示给用户。

图 1-30 显示了索引视图的运行示例。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 1-30。*索引视图的样本运行

总结

HTML5 不仅仅是一组标记元素。它提供了许多现代 web 应用中经常需要的可编程特性。这些特性包括对播放音频和视频文件、画布、网络存储、历史 API、文件 API、网络套接字、网络工作者、离线应用和地理定位的本地支持。

本章给了你一个 HTML5 及其特性的概述。您还了解了 ASP.NET 和 HTML5 是如何结合在一起的。您使用 Modernizr 库在运行时检测 HTML5 特性支持。最后,您开发了两个简单的 web 应用,展示了 HTML5 和 ASP.NET 是如何结合在一起的。这些应用还演示了 jQuery 如何向服务器发出 Ajax 请求并调用服务器端代码,而无需将整个页面提交给服务器。

尽管 HTML5 特性可以使用普通的 JavaScript 编程,但在许多现实情况下,您使用基于 JavaScript 的库(如 jQuery)进行客户端脚本编写。第二章深入研究 jQuery 的细节,让你熟悉它的许多编程结构。

二、jQuery 概述

为了利用 HTML5 的许多特性,您需要使用客户端脚本技术。虽然您可以使用 JavaScript 来完成这项任务,但是使用 jQuery 更容易也更有益。如果您正在开发一个现代的 web 应用,那么您可能已经在使用 jQuery 来满足您的客户端脚本需求了。因此,坚持用 jQuery 编程 HTML5 特性将使您的代码更具可读性、一致性和可管理性。此外,jQuery 提供了许多优于普通 JavaScript 的好处(例如,本章讨论的选择器和 Ajax 调用),您可以在客户端代码中使用这些好处。一些 HTML5 特性要求你从客户端发送数据到服务器。这种数据传输可以通过对服务器的 Ajax 请求有效地完成,jQuery 为发出 Ajax 请求提供了丰富的支持。这里提到的所有好处使 jQuery 成为编写 HTML5 特性的理想选择。

本章介绍了各种 jQuery 特性和构造。然而,这一章并没有试图讨论 jQuery 的每一个微小的特性。它关注的是在 HTML5 编程时经常需要的特性,这些特性将在本书的剩余部分使用。具体来说,您将了解以下内容:

  • Event handling in jQuery
  • JQuery selector
  • Manipulating DOM with Ajax technology in jQuery

面向 Asp.NET 开发者的 HTML5 编程教程(一) 本章涵盖了 jQuery 的基础知识以及如何在 ASP.NET 应用中使用 jQuery。如果你已经熟悉 jQuery,可以跳过这一章。

什么是 jQuery?

jQuery 官方网站([jquery.com](http://jquery.com))对 jQuery 的定义如下:

jQuery 是一个快速而简洁的 JavaScript 库,它简化了 HTML 文档遍历、事件处理、动画和 Ajax 交互,有助于快速的 web 开发。jQuery 旨在改变您编写 JavaScript 的方式。

让我们试着更详细地理解 jQuery 的定义。

jQuery 是一个 JavaScript 库

作为一名 ASP.NET 开发人员,在开发 ASP.NET 网站时,您一定以这样或那样的方式使用过 JavaScript。毫无疑问,普通的 JavaScript 可以帮助你编写丰富的、交互式的、响应性更强的网页;但是你经常需要写太多的代码。例如,如果您希望使用普通的 JavaScript 编写一个客户端脚本来显示一个带有动画效果的漂亮的弹出菜单,这将是一项非常耗时的任务。

为了简化客户端脚本并提高效率,有几个 JavaScript 库可供使用,jQuery 就是其中之一。还有其他的,比如 MooTools,Prototype,Dojo。微软在 ASP.NET 项目中广泛使用 jQuery 的事实清楚地表明了 jQuery 的受欢迎程度以及微软在 ASP.NET 支持它的意图。正如您所料,jQuery 是跨浏览器的,支持所有主流浏览器,包括 Internet Explorer、Firefox、Chrome、Opera 和 Safari。

jQuery 快速而简洁

jQuery 是高度优化的库。而且,它很紧凑。jQuery 1.7.2 的生产版本只有 32KB,开发版本是 247KB。这种紧凑性意味着在客户端下载的数据更少,而不会影响令人惊叹的 UI 效果。

jQuery 简化了 HTML 文档的遍历、事件处理、动画和 Ajax 交互

jQuery 大大简化了 HTML DOM 导航和操作。它提供了许多横向 DOM 树和父子元素的方法。大多数 JavaScript 功能都在客户端事件处理程序中。jQuery 在事件处理方面非常方便,因为连接事件处理程序和处理事件很容易。jQuery 还允许您对 ASP.NET web 服务、web 方法、Windows Communication Foundation(WCF)服务和 MVC 控制器操作进行 Ajax 调用。

jQuery 旨在改变你编写 JavaScript 的方式

jQuery 极大地改变了编写 JavaScript 代码的方式。如果您以前从未使用过 jQuery,最初您可能会发现它的语法有点奇怪;但是一旦你掌握了它,你可能就再也不会看其他的库了(或者至少是传统的 JavaScript 编写方式)。例如,一个普通的 JavaScript 文件包含几个函数,需要时可以单独调用它们。使用 jQuery,操作链使您的代码更加紧凑。jQuery 允许您将方法链接在一起,这样一个方法的输出会被链接中的下一个方法自动处理。这使得在同一个输出上调用多个方法变得更加容易。

下载并参考 jQuery

在使用 jQuery 的任何特性和构造之前,您需要在 Web 表单或 MVC 视图中引用它。可以通过两种方式引用 jQuery 库:

  • Refers to the local copy of jQuery library.
  • Refer to jQuery library of Ajax Content Delivery Network (CDN) from Microsoft.

要引用 jQuery 库的本地副本,应该首先从 jQuery 官方网站([jquery.com](http://jquery.com))下载到本地机器上。如果你创建了一个新的 ASP.NET MVC 项目,jQuery 库会自动放置在Scripts文件夹中(图 2-1 )。当然,如果您希望使用最新版本的 jQuery 库,您需要单独下载它。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-1。*来自 ASP.NET MVC 项目的 jQuery 库

要从微软的 Ajax CDN 引用 jQuery 库,不需要维护 jQuery 库的本地副本——可以直接引用。您可以在微软 Ajax CDN 上的[www.asp.net/ajaxlibrary/cdn.ashx](http://www.asp.net/ajaxlibrary/cdn.ashx)找到可用文件的列表。图 2-2 显示了你可以从微软 Ajax CDN 中使用的文件列表。

jQuery 1.7.2 的简化版本和非简化版本的 URL 如下:

[ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js](http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js)

缩小版是通过应用几种脚本缩小技术(如从代码中删除空格和注释)获得的压缩版本。缩小版是生产使用的理想选择,因为它的尺寸很小。在开发阶段可能需要调试脚本时,可以使用非精简版本。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意CDN 是位于全球关键位置的服务器网络。该网络维护要传送到客户端的文件的缓存副本。当客户端试图访问由 CDN 维护的任何文件时,离请求客户端最近的服务器满足请求。这种技术被称为边缘缓存,因为面向边缘的服务器提供内容。除了 Microsoft Ajax CDN,您还可以使用 Google Libraries API 来引用 jQuery 库。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-2。*微软 Ajax CDN 上的可用文件

无论您保留 jQuery 库的本地副本还是从微软 Ajax CDN 引用它,您都需要添加一个对它的引用,如清单 2-1 所示。

***清单 2-1。*参考 jQuery 库

`  

`

在清单 2-1 中,第一个<script>标签引用了名为Scripts的本地文件夹中的 jQuery 库。请确保更改此路径以匹配您的项目文件夹结构。如果你使用微软 Ajax CDN 来引用 jQuery 库,你的开发机器必须有互联网连接。当然,您可以在开发期间使用 jQuery 库的本地副本,并在应用投入生产后切换到 Microsoft Ajax CDN。

现在您已经知道如何在您的 ASP.NET web 应用中引用 jQuery 库,让我们在接下来的小节中研究 jQuery 的核心特性。

事件处理

处理 HTML 页面元素(如按钮、列表和图像)引发的事件是客户端脚本中最常见的编程操作之一。jQuery 提供了一种简单的跨浏览器事件处理机制,允许您动态连接事件处理程序,并提供关于正在处理的事件的丰富信息。

表 2-1 列出了 web 应用中许多常用的客户端事件。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

为了处理表 2-1 中的事件,jQuery 提供了一组相应的函数。这些功能有双重用途:

  • They let you specify an event handler function that should be executed when an event occurs.
  • They let you trigger events programmatically.

例如,要将一个名为OnClick的事件处理函数连接到一个 ID 为Button1的按钮的click事件,您需要编写

$("#Button1").click(OnClick);

另一方面,如果您希望以编程方式触发Button1click事件,您可以编写:

$("#Button1").click();

当您在本节开发的示例中使用它时,这种双重目的会更加清晰。

jQuery 事件处理的一个很好的特性是,事件对象以标准的方式传递给事件处理程序,并且在所有浏览器中包含相同的属性集。传递给事件处理程序的事件对象包含几条信息,如表 2-2 中所列。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

event 对象还提供了一个方便的方法preventDefault(),用于取消事件的默认动作。

为了理解如何使用 jQuery 处理事件,让我们开发一个 ASP.NET Web 表单应用,如图 2-3 所示。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-3。*使用 jQuery 事件处理的字符计数器

图 2-3 中的所示的 web 表单有一个<textarea>用于输入自由格式的文本数据。但是,您可以设置可以输入的最大字符数。在运行时,当用户开始输入时,字符计数器显示仍可输入的字符数。如果输入文本的长度超过预定义的值,您可以禁止进一步输入,或者用彩色高亮显示负字符数。当用户单击 Submit 按钮时,会要求他们确认是否要提交表单;因此,要么将表单提交给服务器,要么取消操作。

清单 2-2 显示了 web 表单的 HTML 标记。

***清单 2-2。*字符计数器表单的 HTML 标记

`
Enter some text :


Character counter :

`

“提交”按钮和关联的消息标签是服务器控件。通常,标记中使用的 CSS 类驻留在样式表文件中。接下来,您需要编写 jQuery 代码,连接几个事件处理程序并使字符计数器起作用。清单 2-3 显示了为keyupblurclick事件连接事件处理程序的ready()函数。keyupblur事件处理程序确保在textarea中输入的字符数小于或等于最大长度。它们还更新相应的<span>元素中的字符数。

***清单 2-3。*字符计数器的事件接线

`KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: …ounter’   };   (“#textarea”).keyup(eventData, OnKeyUp);
  KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲textarea”).blur…(“#textarea”).keyup();

$(“#submit”).click(function (event) {
    if (!confirm(“Do you wish to submit the form?”)) {
      event.preventDefault();
    }
  });
})`

当浏览器中加载了整个 HTML DOM 树时,jQuery 会自动调用ready()函数。您可以将自己的函数传递给ready()函数,该函数为各种元素(如textarea<button>)连接事件处理程序。代码声明了一个变量(eventData),该变量存储需要传递给事件处理程序的配置设置。一旦连接了事件处理程序,每次引发事件时,eventData对象会自动传递给事件处理程序。注意eventData是一个 JSON 对象,采用键值对的形式。键及其值由冒号(:)分隔,多个键值对由逗号(,)分隔。表 2-3 解释了eventData对象的每个设置的用途。

然后代码选择<textarea>元素。注意基于 ID 选择元素的 jQuery 方式:您需要传递前缀为#字符的元素 ID。<textarea>keyupblur事件分别连接到OnKeyUpOnBlur事件处理函数。您很快就可以编写这些事件处理函数。注意,在连接事件处理程序时,代码也传递了eventData对象。然后代码通过调用keyup()函数以编程方式触发<textarea>keyup事件。这使得 counter <span>元素显示初始字符数。

提交按钮的click事件的事件处理程序使用不同的语法连接。代码创建了一个匿名事件处理程序(也称为内联函数)函数,而不是创建一个单独的函数,然后将其作为事件处理程序附加。事件处理函数接受一个参数(event ),该参数在引发click事件时自动传递。提交按钮的click事件处理程序询问用户是否提交表单。如果用户决定取消表单提交,则使用事件对象的preventDefault()方法取消click事件。

事件处理函数OnKeyUp()如清单 2-4 所示。

***清单 2-4。*处理keyup事件

function OnKeyUp(event) {   var id = "#" + event.target.id;   var counterid = "#" + event.data.CounterId;   var text = $(id).val();   if (text.length > event.data.MaxLength) {     if (!event.data.AllowOverflow) {       $(id).text(text.substring(0, event.data.MaxLength));     }   }   var diff = 0;   if (event.data.Type == 'Remaining') { ...   }   else { ...  }   $(counterid).text(diff); }

注意如何使用event.target.id来检索<textarea>的 ID,如何使用event.data.CounterId来检索<span>的 ID。这些 id 存储在两个变量中(idcounterid)以备后用。val()方法返回在<textarea>中输入的文本,并存储在另一个局部变量(text)中。根据计数器的类型(RemainingTotal,代码根据MaxLength值检查<textarea>中输入的文本数据的长度。如果TypeRemaining,则检查如下:

diff = event.data.MaxLength - $(id).val().length; if (diff < 0) {   $(counterid).removeClass(event.data.NormalCss);   $(counterid).addClass(event.data.WarningCss); } else {   $(counterid).removeClass(event.data.WarningCss);   $(counterid).addClass(event.data.NormalCss); }

如果文本长度与MaxLength之差小于 0,则表明文本长度超过了最大允许长度。在这种情况下,您应该显示带有WarningCss类的计数器。为此,首先使用removeClass()方法移除NormalCss类,然后使用addClass()方法应用WarningCss类。如果差值大于 0,您应该通过移除WarningCss类来应用NormalCss类。

如果计数器TypeTotal,则应用 CSS 类,如下所示:

diff = $(id).val().length; if (diff > event.data.MaxLength) {   $(counterid).removeClass(event.data.NormalCss);   $(counterid).addClass(event.data.WarningCss); } else {   $(counterid).removeClass(event.data.WarningCss);   $(counterid).addClass(event.data.NormalCss); }

如果输入的文本长度大于MaxLength值,则使用removeCss()方法移除NormalCss类,并使用addClass()应用WarningCss类。否则,移除WarningCss并应用NormalCss

最后,在代码基于Type设置执行长度检查之后,使用text()方法将计数器值分配给<span>元素。

如果AllowOverflow设置为false,用户输入的更多文本将使用substring() JavaScript 函数被修剪为MaxLength的值。使用text()方法将修剪后的文本分配给<textarea>

OnBlur()事件处理函数如清单 2-5 所示。

***清单 2-5。*处理blur事件

function OnBlur(event) {   var id = "#" + event.target.id;   $(id).keyup(); }

OnBlur()事件处理函数只是以编程方式触发keyup事件。这样,即使用户使用复制粘贴技术(Ctrl+V 或快捷菜单)在<textarea>中输入文本,当用户退出<textarea>时,计数器仍然会反映正确的值。

图 2-4 显示了文本超过MaxLength值的 web 表单的运行示例。您还可以测试提交按钮的功能。注意,如果单击 Cancel,表单不会回发到服务器。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-4。*字符计数器显示警告

在您刚刚开发的字符计数器中,您使用了#id语法来选择一个与特定 ID 匹配的 DOM 元素。通过这样做,您使用了 jQuery 众多选择器中的一个。下一节将介绍 jQuery 中其他一些重要的选择器。

使用 bind()方法进行事件关联

在前面的例子中,您分别使用 jQuery 函数click()change()连接了标准事件clickchange的事件处理程序。在撰写本文时,jQuery 还没有包含特定于 HTML5 的事件的事件函数。例如,您在第三章中了解到的video元素有playpause事件,但是 jQuery 没有内置函数来连接这些事件的事件处理程序。幸运的是,jQuery 提供了一种将事件连接到它们的处理程序的通用方法:bind()方法。您可以按如下方式使用它:

$("#Button1").bind("click",OnClick);

这行代码将Button1click事件连接到一个名为OnClick的事件处理函数。bind()方法有两个参数。第一个参数指示您希望处理的事件,第二个参数指定事件处理函数。

jQuery 选择器

使用客户端脚本时,您通常只需要对特定的元素执行某些任务。例如,您可能想要读取 ID 为TextBox1的文本框的值,或者用红色显示表格中包含负值的所有行。jQuery 选择器允许您根据特定标准匹配 HTML 元素,并选择它们进行进一步处理。因此,jQuery 选择器返回一个集合,其中包含零个或多个与选择标准匹配的元素。

jQuery 选择器可以分为以下几类:

  • Basic selector: Select elements according to basic criteria such as ID, CSS class and HTML tag name.
  • Basic filtering: Filter the element set according to the conditions of first occurrence, last occurrence, odd or even elements, etc.
  • Attribute selector: Select elements by matching attribute values.
  • Sub-level filtering: Filter the element set according to the conditions of the first sub-level, the last sub-level, the nth sub-level, the unique sub-level, etc.
    ** Content filter: Filter elements according to content.* Form selector: Select form elements according to type (button, check box, etc.) and status (selected or selected).* Hierarchy selector: Select elements (child elements, descendant elements, brother elements and adjacent elements) from the hierarchy.* Visibility filter: Select elements according to their visibility status (visible or hidden).*

*本书示例中经常用到的选择器将在下面的章节中讨论。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意下面几节中讨论的一些示例使用了 Northwind 数据库,这是微软为 SQL Server 开发的一个示例数据库。因此,您可以考虑将其安装在本地 SQL Server 或 SQL Server Express 实例中。您可以从 MSDN 下载中心下载 Northwind 数据库的 T-SQL 脚本。

根据 ID、标签名和 CSS 类选择元素

基于 ID、标记名或 CSS 类选择 HTML 元素是客户端脚本编写中的一个常见需求。从前面几节中,您已经知道了如何通过指定 ID 来选择 HTML 元素。清单 2-6 显示了这三种类型的选择。

***清单 2-6。*使用 ID、标签名和 CSS 类来匹配元素

$(document).ready(function () {   $("#myDiv").html("<h1>Hello jQuery !</h1>");   $("div").css("background-color", "#ded8d8");   $(".MyClass").text("We have the same CSS class!"); })

ready函数中的第一行选择了一个 ID 为myDiv的 DOM 元素。然后,它使用 jQuery html()方法将所选元素的 HTML 内容设置为一些标记。第二行从页面中选择所有的<div>元素,并使用css()方法将它们的背景色设置为#ded8d8。最后,第三行代码选择应用了名为MyClass的 CSS 类的所有元素,并将它们的 HTML 内容设置为一个字符串。

图 2-5 显示了该页面的运行示例。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-5。*根据 ID、标签名和 CSS 类选择 HTML 元素

注意所有的<div>元素都有相同的背景颜色,因为颜色被应用到标签名为div的所有 HTML 元素的background-color属性。类似地,CSS 类MyClass的两个<div>元素具有相同的文本内容。

现在,让我们基于这些知识开发一个更有意义的例子。图 2-6 显示了一个GridView服务器控件,其中填充了来自 Northwind 数据库Employees表的数据。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 2-6。 GridView用不同的样式显示交错的行

GridView控件在浏览器中呈现为一个 HTML 表格。图 2-6 中所示的GridView具有以不同 CSS 样式显示的交替行。此外,标题行以另一种 CSS 样式显示。此外,当鼠标指针悬停在这些行上时,它们会显示一个突出显示的标记。单击任何一行都会在警告框中显示该行的EmployeeID。所有这些都是通过 jQuery 完成的。web 表单中的<script>块显示了清单 2-7 中的 jQuery 代码。

***清单 2-7。*用不同的样式标记奇数行和偶数行

$(document).ready(function () {   $("#GridView1 th").parent().addClass("HeaderRow");   $("#GridView1 tr:not(.HeaderRow):odd").addClass("Row");   $("#GridView1 tr:not(.HeaderRow):even").addClass("AlternateRow");   $("#GridView1 tr:not(.HeaderRow)").hover(function () {     $(this).addClass('HoverRow');   }, function () {     $(this).removeClass('HoverRow');   }).click(function () {     if ($(this).hasClass("HeaderRow")) {       alert("This is header row. Can't get EmployeeID!");     }     else {       alert("You selected Employee ID :" + $("td:first", this).text());     }   }); });

清单 2-7 中显示的代码使用了本节前面讨论的选择器和一些附加过滤器的组合。首先,代码为表格的标题行设置一个 CSS 类。注意来自特定GridView(ID 为GridView1)的<th>元素是如何被选择的。这样,即使同一个 web 表单上有多个表格,样式也只应用于GridView1parent()方法返回一个父元素<th>(在本例中为<tr>),并且使用addClass()方法将HeaderRow CSS 类应用于该表格行。

接下来的两行代码从表中选择所有奇数和偶数行,不包括标题行。这通过使用:not():odd:even选择器来完成。:not()选择器确保不选择标题行来应用奇数和偶数样式。:odd:even选择器分别返回奇数和偶数元素。一旦选中,CSS 类RowAlternateRow将分别应用于它们。

接下来,使用hover()方法将鼠标悬停效果添加到表格行。hover()方法的第一个参数是当鼠标指针进入表格行时调用的函数,第二个参数是当鼠标指针离开表格行时调用的函数。在回调函数中,关键字this代表当前表格行。hover()方法函数本质上是添加和删除HoverRow CSS 类到考虑中的表格行。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意在任何 jQuery 事件处理程序中,关键字this都是指事件处理程序所附加的 DOM 元素。

注意在连接click事件处理程序时 jQuery 链接特性的使用。不用再次选择行,然后连接它们的click事件处理程序,您可以同时连接hoverclick事件的事件处理程序。

click事件处理程序显示被点击行的EmployeeIDtd:first选择器返回当前行的第一个td元素。在不带任何参数的情况下调用text()方法时,该方法返回该表列中的文本内容(在本例中为EmployeeID)。如果单击标题行,将显示一条错误消息。注意如何使用hasClass()方法来确定一行是否应用了特定的 CSS 类。

根据属性值选择元素

属性选择器允许您将 HTML 元素的属性与某些标准相匹配。它不仅限于对等匹配;也有其他几种选择,如表 2-4 中所列。使用属性选择器的一般形式如下:

<element_name>[<attribute_name> <operator> <value_to_match>]

面向 Asp.NET 开发者的 HTML5 编程教程(一)

让我们考虑一些展示如何使用属性选择器的例子。

假设您有一个包含许多超链接的网页,并且您希望选择那些href属性正好等于[www.microsoft.com](http://www.microsoft.com)的超链接。下面的属性选择器完成了这个任务。警告框显示所选元素的总数:

alert($("a[href = 'http://www.microsoft.com']").length);

假设你有几个超链接:[microsoft.com](http://microsoft.com)[msdn.microsoft.com](http://msdn.microsoft.com)[www.asp.net](http://www.asp.net)。你只需要选择那些包含单词微软的超链接。以下属性包含选择器选择前两个超链接,但不选择第三个:

alert($("a[href *= 'microsoft.com']").length);

假设一个产品目录页面显示了许多图片。其中一些是产品图像,另一些是网站主题图像(徽标、菜单等)。还假设产品图像存储在名为product的文件夹中。要选择所有要处理的产品图像,您可以使用这个属性以选择器返回其src属性以产品开始的图像元素:

alert($("img[src ^= 'product']").length);

假设您正在构建一个相册 web 应用,它以各种格式显示照片,包括.png.jpg.gif。根据图像格式,您可以允许添加某些特殊效果。在这种情况下,您可能想要选择具有特定文件扩展名的图像。下面的属性以结尾选择器通过选择所有src属性以.gif结尾的图像来完成:

alert($("img[src $= '.gif']").length);

假设一个多语言网站需要用不同的语言呈现其内容。lang属性用于标记页面某一部分的语言。如果您希望选择所有的<div>元素,它们的lang属性被设置为某个值,您可以使用这个 has 属性选择器:

alert($("div[lang]").length);

现在,让我们开发一个使用属性选择器的更真实的例子,如图 2-7 所示。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-7。*使用属性选择器过滤下载链接

在图 2-7 中,web 表单由一个GridView控件组成,该控件显示可下载文件的链接。下载类别在顶部的DropDownList中列出。当用户选择特定类别时,只显示属于所选类别的下载。其余的都藏起来了。下载链接有特定的模式:

  • All product download links contain the Products folder in UR: for example, products/Product1Setup.exe.
  • The download links of all white papers are in paper-*xxxx* format, where xxxx is the title of the paper: for example, Paper-Topic1.pdf.
  • The download links of all software components are in the form of *xxxx*-comp.zip: for example, Component1-comp.zip.

下载链接的隐藏和显示发生在客户端,使用 jQuery 属性选择器。清单 2-8 展示了这段代码的框架。

***清单 2-8。*使用属性选择器隐藏或显示下载链接

$(document).ready(function () {   $("#DropDownList1").change(function () {     switch ($("#DropDownList1").val()) {       case "A":       case "P":       case "WP":       case "C":     }   }) })

ready函数为DropDownList1change事件连接一个事件处理程序。正如您可能猜到的,当DropDownList中的选择改变时,就会引发change事件。change事件处理程序由一个 JavaScript switch语句组成,该语句检查所选的值。让我们讨论一下每个案例部分的内容。

如果选择的值是"A",意味着所有下载,那么所有表格行的display CSS 属性被设置为block。这确保所有类型的下载(产品、组件和白皮书)都显示在网格中:

`case “A”:

$(“#GridView1 tr a”).parent().css(“display”, “block”);
  break;`

如果选择的值是"P"(产品),那么属性包含选择器(*=)用于匹配所有href属性包含字符串"products/"的锚元素。匹配后,将显示包含匹配超链接元素的表格行,其他行保持隐藏状态:

case "P":   $("#GridView1 tr a[href *= 'products/']").parent().css("display", "block");   $("#GridView1 tr a[href |= 'Paper']").parent().css("display", "none");   $("#GridView1 tr a[href $= '-comp.zip']").parent().css("display", "none");   break;

如果选择的值是"WP"(白皮书),代码使用属性包含前缀选择器(|=)来选择以文本“paper”为前缀的超链接。注意白皮书的 URL 以"Paper-"开始,但是选择器只指定了"Paper";这是因为在匹配元素时,属性包含前缀选择器自动采用连字符(-)。选定后,包含这些超链接的表格行将显示,而其他行将保持隐藏状态:

case "WP":   $("#GridView1 tr a[href *= 'products/']").parent().css("display", "none");   $("#GridView1 tr a[href |= 'Paper']").parent().css("display", "block");   $("#GridView1 tr a[href $= '-comp.zip']").parent().css("display", "none");   break;

最后,如果选择的值是"C"(组件),代码使用属性选择与组件相关的链接,以选择器($=)结束,并相应地显示和隐藏表格行:

case "C":   $("#GridView1 tr a[href *= 'products/']").parent().css("display", "none");   $("#GridView1 tr a[href |= 'Paper']").parent().css("display", "none");   $("#GridView1 tr a[href $= '-comp.zip']").parent().css("display", "block");   break;

选择表单元素

表单选择器允许您根据 HTML <form>元素的类型(文本框、复选框、单选按钮等)或状态(选中、选中或禁用)来选择 HTML<form>元素。表 2-5 列出了各种可用的表单选择器。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

清单 2-9 显示了表 2-5 中提到的一些选择器。

***清单 2-9。*表单选择器的基本用法语法

$(document).ready(function () {   $("#form1 :text").attr("disabled", "disabled");   $("#form1 :checkbox").attr("checked", "checked");   $("#Button1").click(function () {     alert($("#form1 input[type='checkbox']:checked").length + " checkboxes are checked.");     alert($("#Select1 option:selected").length + " options are selected.");   }); });

清单 2-9 中的第一个表单选择器选择所有文本框,并通过添加disabled属性禁用它们。jQuery attr()函数用于设置元素的属性值。attr()的第一个参数是属性的名称,第二个参数是它的值。在这种情况下,disabled属性被设置为值disabled,以便禁用文本框。

第二个表单选择器选择所有复选框,并通过添加checked属性以编程方式选中它们。

Button1click事件处理程序选择所有选中的复选框元素。jQuery 选择器可以返回零个或多个元素。使用length属性可以获得所选元素的总数。在这种情况下,会出现一个警告框,显示选中的复选框总数。

最后,最后一个警告框显示从一个<select>元素中选择的所有选项的数量。

图 2-8 所示的 web 表单演示了表单选择器的一个更真实的用法。web 表单显示了一个包含来自 Northwind 数据库的Employees表的记录的GridViewGridView的每一行都有一个复选框和一个单选按钮来选择那一行。复选框列的标题中还有一个复选框,用于切换所有复选框的选择。顶部的列表框显示城市;如果在列表框中选择一个或多个城市,则只有属于所选城市的员工记录才被启用。其他记录的复选框和单选按钮被禁用。单击清除选择按钮清除列表框中的所有选择,并启用所有员工行。负责此功能的 jQuery 代码由四个事件处理函数组成:复选框的change事件处理函数、单选按钮的change事件处理函数、list boxchange事件处理函数和按钮的click事件处理函数。这些事件处理程序连接在ready()函数中,接下来将会讨论。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 2-8。 A GridView显示用于选择员工行的复选框和单选按钮

清单 2-10 显示了复选框的change事件处理程序。

***清单 2-10。*复选框的Change事件处理程序

$("#GridView1 :checkbox[id$='chkHeader']").change(function () {   if ($("#GridView1 :checked[id $='chkHeader']").is(":checked")) {     $("#GridView1 :checkbox[id *='chkItem']").attr("checked", "checked");   }   else {     $("#GridView1 :checkbox[id *='chkItem']").removeAttr("checked");   } })

清单 2-10 中的代码连接了标题行中复选框的change事件处理程序。它使用以属性选择器结束的来实现,因为在运行时,GridView为复选框生成唯一的 id。在生成这些唯一 ID 时,由开发人员设置的设计时 ID 被附加在唯一字符串值的末尾。例如,header 复选框的 ID 属性设置为chkHeader,在运行时其客户端 ID 变为GridView1$ctl01$chkHeader。标题复选框的change事件处理程序从GridView行中选择所有复选框,并根据标题复选框的状态切换它们的状态。通过使用 jQuery attr()方法添加或删除checked属性来切换复选框状态。

所有单选按钮的change事件处理程序如清单 2-11 中的所示。

清单 2-11。 Change单选按钮的事件处理程序

$("#GridView1 :radio[id *='radItem']").change(function () {   var newId = this.id;   $("#GridView1 :radio[id *='radItem']").each(function (index) {     if (this.id != newId) {       $(this).removeAttr("checked");     }   }) })

默认情况下,放置在GridView中的单选按钮不是互斥的,您可以选择多个单选按钮。发生这种情况是因为GridView为每个单选按钮生成了不同的名称,而不是将它们视为一个组。为了解决这个问题,单选按钮的change事件处理程序遍历单选按钮,并取消选中除被选中按钮之外的所有按钮。为了遍历单选按钮,代码使用了 jQuery each()方法。each()方法采用一个函数,对匹配集中的每个元素执行该函数。回调函数从匹配集中接收当前元素的从零开始的索引。要取消选中一个单选按钮,使用removeAttr()方法删除它的checked属性。

显示城市的列表框的change事件处理程序如清单 2-12 所示。

清单 2-12。 Change列表框的事件处理程序

$("#ListBox1").change(function () {   $("#GridView1 :input").attr("disabled", "disabled");   $("#ListBox1 option:selected").each(function () {     $("#GridView1 tr:contains('" + this.value + "')").each(function () {       $(":input", this).removeAttr("disabled");     })   }) })

该事件处理程序禁用所有输入元素,包括复选框和单选按钮。然后,它选择列表框中的选项,并使用each()方法逐个遍历它们。each()块中的代码检查当前行是否包含选择的城市。使用:contains()选择器完成该检查。该选择器接受一个字符串,并只返回那些包含指定字符串值的行。如果在一行中找到一个城市,则使用removeAttr()方法删除相应复选框和单选按钮的disabled属性。

清除选择按钮的click事件处理程序如清单 2-13 所示。

清单 2-13。 Click清除选择按钮的事件处理程序

$("#Button1").click(function (event) {   $("#ListBox1 option").each(function () {     $(this).removeAttr("selected");   })   $("#GridView1 :input").removeAttr("disabled");   event.preventDefault(); })

按钮的click事件处理程序使用each()方法遍历所有列表框选项,并通过移除selected属性逐个取消选择它们。所有的<input>元素都是通过删除disabled属性来启用的,因为现在列表框中没有城市被选中。

使用 jQuery 修改 DOM

到目前为止,您已经知道了如何改变现有的元素及其属性。jQuery 还允许您插入、追加、删除和替换 HTML DOM 中的元素,以便您可以修改文档结构。例如,假设您从客户端 jQuery 代码调用一个远程服务,根据服务返回的内容,您需要动态生成 HTML 标记。这些任务可以使用 jQuery 方法来完成,这些方法允许您操作 HTML DOM。表 2-6 列出了一些最常用的 DOM 操作方法。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

面向 Asp.NET 开发者的 HTML5 编程教程(一)

你已经熟悉了其中的一些方法,比如val()attr()removeAttr()text()html()。清单 2-14 显示了来自表 2-6 的其他方法的使用。

***清单 2-14。*使用 DOM 操作方法

$("#container").append("<div>Hello</div>"); $("<div>Hello</div>").appendTo("#container"); $("span").replaceWith("<div class='class1'>Hello Universe!</div>"); $("<div class='class2'>Hello World!</div>").replaceAll("div.class1");

清单 2-14 中的第一行代码在容器元素的末尾添加了<div>Hello</div>。所以,如果容器是一个<span>元素,那么在调用append()方法之后,有效的标记是

<span id='container'><div>Hello</div></span>

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意大多数浏览器都让你查看正在显示的网页的 HTML 源代码。然而,这个 HTML 源代码不包括任何在运行时使用表 2-6 中列出的 jQuery 方法动态添加的 HTML 标记。

第二行代码使用了appendTo()方法。该方法类似于append()方法,但有一点不同:append()在目标元素上被调用,并接受要追加的标记。appendTo()方法接受一个目标元素作为参数,并在目标的末尾附加指定的标记。

replaceWith()方法的例子用<div class='class1'>元素替换了所有的<span>元素。比如,如果原来的标记是<span>Hello World!</span>,那么调用replaceWith()方法后,新的标记就是<div class='class1'>Hello Universe!</div>

最后,replaceAll()方法用 CSS 类class1替换所有的<div>元素,用<div>Hello World!</div>替换。

jQuery Ajax 技术

在后面章节中讨论的许多 HTML5 特性要求你在客户机浏览器和服务器之间传递数据。这种数据传输可以通过两种方式完成:

  • Submit the entire form to the server.
  • Make Ajax requests to the server

第一种技术涉及使用GETPOST请求将整个表单提交给服务器。尽管这是一种经典技术,并且易于实现(使用提交按钮或submit() JavaScript 方法),但它有一个缺点:整个页面需要刷新,这会影响 web 应用的响应能力和整体性能。难怪许多现代 web 应用倾向于使用第二种方式向服务器发送数据。

第二种技术是向服务器发出一个 Ajax 请求。使用 Ajax 的好处是不需要将所有的表单数据发送到服务器。相反,您可以只发送在给定时间点进行处理所需的数据片段。Ajax 请求返回的处理结果可用于动态更新网页。因此,Ajax 提高了 web 应用的响应能力和整体性能。

注意,虽然 Ajax 意味着使用 XML 作为数据格式,但 JSON 由于其紧凑性而比 XML 更常用。本书中大多数需要在客户机和服务器之间传输数据的例子都使用了 Ajax 和 JSON。

jQuery 提供了许多向服务器发出 Ajax 请求的方法。它们列在表 2-7 中。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

使用 jQuery Ajax 技术,您可以调用以下类型的 ASP.NET 服务器端代码:

  • Web service (.asmx)
  • Web method
  • WCF service (.svc)
  • ASP.NET MVC controller action method
  • Web API
  • Universal HTTP handler (.ashx)

尽管 jQuery Ajax 技术允许您调用 ASMX web 服务,但只要有可能,就应该避免使用它们,因为有更新的技术可用。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意从技术上讲,你可以向这里没有列出的任何服务器端资源发出 Ajax 请求。然而,在大多数情况下,最好将要从客户端调用的代码封装在所讨论的一种机制中。

对表 2-7 中列出的所有 jQuery Ajax 技术的详细讨论超出了本书的范围。下面的例子说明了$.ajax()函数的用法,因为它是所有其他技术的鼻祖。

本节中的例子展示了如何在 Web 表单和 MVC 应用中使用$.ajax()。你开发的两个应用都显示一个简单的网页,如图 2-9 所示。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-9。*在摄氏和华氏之间转换温度的网页

该网页允许您输入摄氏或华氏温度值,并将其转换为其他刻度。温度转换发生在 Web 窗体应用的 WCF 服务和 MVC 应用的控制器操作方法中。

使用 jQuery $。Web 窗体应用中的 ajax()方法

在摄氏和华氏之间转换温度值的 WCF 服务如清单 2-15 中的所示。

清单 2-15。 WCF 温度值转换服务

`namespace AjaxWebForm
{
    [DataContract]
    public class TemperatureData
    {
        [DataMember]
        public decimal Value { get; set; }
        [DataMember]
        public string Unit { get; set; }
    }

[ServiceContract]
    public interface IService
    {
        [OperationContract]
        [WebInvoke(Method = “POST”,
          RequestFormat = WebMessageFormat.Json,
          ResponseFormat = WebMessageFormat.Json)]         TemperatureData Convert(TemperatureData t);
    }

public class Service : IService
    {
        public TemperatureData Convert(TemperatureData t)
        {
            if (t.Unit == “C”)
            {
                t.Value = (t.Value * 1.8m) + 32;
                t.Unit = “F”;
            }
            else
            {
                t.Value = (t.Value – 32) / 1.8m;
                t.Unit = “C”;
            }
            return t;
        }
    }
}`

TemperatureData类表示 WCF 服务的数据契约,包含两个数据成员属性:ValueUnitIService接口表示服务的服务契约,并定义了一个方法Convert()Convert()方法接受一个TemperatureData对象,并在将温度值转换为另一个刻度后返回一个TemperatureData对象。

请注意,Convert()是用一个[WebInvoke]属性修饰的。由于这个属性,Convert()变得可以从客户端 jQuery 代码中调用。[WebInvoke]属性的RequestFormatResponseFormat属性分别指定 JSON 作为请求和响应期间的通信格式。属性指定 HTTP POST请求可以调用Convert()Service类实现了Convert()Convert()方法检查传入的TemperatureData对象的Unit,并根据UnitValue转换为另一个刻度。

可以使用 jQuery 的$.ajax()函数调用Service类的Convert()方法,如清单 2-16 所示。

***清单 2-16。*使用$.ajax()调用 WCF Service Convert()的方法

$(document).ready(function () {   $("#Button1").click(function () {     url = "Service.svc/Convert";     data = '{"Value":"' + $("#Text1").val() + '","Unit":"' + $("#Select1").val() + '"}';     $.ajax({       type: "POST",       url: url,       data: data,       contentType: "application/json; charset=utf-8",       dataType: "json",       success: OnSuccess,       error: OnError     })   }); }); `function OnSuccess(results) {
  alert(“Converted Temperature : ” + results.Value + ” ” + results.Unit);
}

function OnError(err) {
  alert(err.status + ” – ” + err.statusText);
}`

Convert 按钮的click事件处理程序包含用于调用Convert()方法的 jQuery 代码。$.ajax()功能有许多可配置的设置。清单 2-14 中使用了一些常见的。url设置允许您指定远程资源 URL。对于 WCF 服务,URL 采用<path_to_svc_file>/<method_name>的形式。

type选项允许您指定发出请求时要使用的 HTTP 请求类型。Convert()方法配置了[WebInvoke]属性来使用POST方法,因此type就是POSTdata设置表示在进行呼叫时要发送给服务器的数据(如果有)。注意数据是如何以 JSON 格式捕获的。JSON 对象采用键值对的形式:一个键和它的值由冒号(:)分隔,多个键值对由逗号(,)分隔。

dataType设置控制响应的数据类型(XML、JSON 等)。回想一下,[WebMethod]属性将ResponseFormat指定为 JSON,因此这里的dataType必须设置为 JSON 才能正确处理来自服务器的数据。

如果Convert()成功返回,则调用成功选项(OnSuccess)指定的函数。如果调用 WCF 服务时出现任何错误,将调用由错误选项(OnError)指定的函数。OnSuccess()函数是处理从 WCF 服务返回的数据的地方。OnSuccess()接收Convert()(TemperatureData对象)的返回值作为参数。您可以访问它的ValueUnit属性,并向用户显示一个警告框。

OnError()函数中,您通常会向用户标记错误或者采取一些纠正措施。OnError()接收一个错误对象;您可以向用户显示它的statusstatusText属性。

图 2-10 显示了 Web 表单应用的运行示例。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 2-10。*转换温度的 Web 表单应用运行示例

使用 jQuery $。MVC 应用中的 ajax()方法

使用 MVC 应用并从 jQuery 调用服务器端代码非常简单。您不需要创建一个单独的服务(当然,如果您愿意,您可以这样做)。相反,您可以将代码封装在控制器动作方法中。例如,清单 2-17 显示了封装温度转换逻辑的Convert()动作方法。

清单 2-17。Convert()MVC 控制器中的动作方法

public JsonResult Convert(TemperatureData t) {     if (t.Unit == "C")     {         t.Value = (t.Value * 1.8m) + 32;         t.Unit = "F";     }     else     {         t.Value = (t.Value - 32) / 1.8m;         t.Unit = "C";     }     return Json(t); }

如您所见,Convert()动作方法接受一个类型为TemperatureData的参数,并返回一个JsonResultJsonResult类以 JSON 格式包装返回值。注意如何使用 ASP.NET MVC 的Json()方法返回JsonResult对象;该方法接受要返回的数据,并将其转换为 JSON 格式。

您可以通过编写如清单 2-18 所示的 jQuery 代码从客户端调用Convert() action 方法。

***清单 2-18。*通过$.ajax() () 调用控制器动作方法

`KaTeX parse error: Expected ‘}’, got ‘EOF’ at end of input: …unction () {   (“#Button1”).click(function () {
    url = “/Home/Convert”;
    data = ‘{ Value: “’ + $(“#Text1”).val() + ‘”, Unit: “’ + KaTeX parse error: Expected ‘EOF’, got ‘#’ at position 3: (“#̲Select1”).val()….ajax({
      type: “POST”,
      url: url,
      data:data,
      contentType: “application/json; charset=utf-8”,
      dataType: “json”,
      success: OnSuccess,
      error: OnError
    })
  });
});

function OnSuccess(results) {
  alert(“Converted Temperature : ” + results.Value + ” ” + results.Unit);
} function OnError(err) {
  alert(err.status + ” – ” + err.statusText);
}`

这段代码类似于清单 2-16 ,有一点小小的不同:发送POST请求的 URL 的形式是<controller_name>/<action_method_name>。如果您运行 MVC 应用,您应该得到与 Web 窗体应用相同的结果。

总结

HTML5 特性可以用普通的 JavaScript 编程,但是使用 jQuery 这样的库可以提供更丰富的功能和易用性。jQuery 是一个流行的 JavaScript 库,让您的客户端脚本编写变得轻而易举。使用 jQuery 选择器,您可以根据复杂的条件选择 HTML DOM 元素。您还可以动态操作 HTML DOM。当您需要在客户机和服务器之间传递数据时,jQuery 可以帮上忙。jQuery Ajax 技术允许您向服务器发出请求,而无需提交整个页面。

本章概述了 jQuery 的核心特性,比如事件处理、选择器、DOM 操作和 Ajax 技术。您将在本书的剩余部分使用这些特性(以及更多特性)。掌握了这些技能,下一章是时候探索 HTML5 音频和视频 API 了。*

三、处理音频和视频

十多年前建立的网站主要是静态 HTML 页面的集合。然后是 JavaScript,网页变得更加互动和生动。然而,富媒体网站仍处于起步阶段。这些年来,情况在很大程度上发生了变化。支持音频和视频的网站并不少见。像 YouTube 这样的视频分享网站已经变得非常流行。除了这种媒体疯狂,社交网站如脸书和 Google+让你只需点击鼠标就能分享视频。底线是富媒体网站在未来几年将变得越来越普遍。

对于 HTML5 之前的 web 应用,开发人员需要依赖第三方插件来显示音频和视频文件。这是因为 HTML 4.01 没有播放媒体文件的原生支持。原生支持意味着 HTML 标记和浏览器可以显示媒体文件,而不需要任何外部插件或应用。HTML5 将改变这一局面:它为播放音频和视频文件提供了原生支持。不仅如此,它还公开了音频和视频 API,允许您控制媒体文件在浏览器中的播放方式。本章涵盖了使用 HTML5 的音频和视频功能所需的所有知识。具体来说,您将了解以下内容:

  • Use <audio> element
  • Use <video> element
  • Media formats supported by mainstream browsers
  • HTML5 is not supported in the browser.
  • Create a custom video player using audio and video APIs and jQuery

使用<对象>标签嵌入媒体文件

在讨论特定于 HTML5 的播放音频和视频文件的方式之前,让我们先来看一下目前普遍使用的技术。尽管 HTML5 为在网页中嵌入音频和视频文件提供了本机支持,但并非所有浏览器都支持 HTML5。为了确保您的网页在这样的浏览器中正常工作,您可以使用本节中讨论的技术作为后备机制。

HTML <object>标签是一个通用标签,允许你在网页中嵌入对象:媒体文件,ActiveX 控件,Java 小程序,甚至 PDF 文件。然而,它更常用于显示音频和视频文件。<object>标签需要第三方插件来加载和播放媒体文件;您可以使用基于 Adobe Flash、Apple QuickTime 和 Microsoft Silverlight 的插件。如果目标机器没有安装所需的插件,媒体文件将拒绝播放。

下面几节说明如何使用<object>标签来播放音频和视频文件。

嵌入音频文件

要将一个音频文件嵌入到网页中,你可以使用一个<object>标签,如清单 3-1 所示。

***清单 3-1。*使用<object>标签播放音频文件

`

Play Audio File

`

<object>标签的data属性指向一个驻留在Media文件夹中的 MP3 音频文件。

嵌入 Flash 视频文件

Adobe Flash 是在网页中嵌入视频文件的最流行的方式之一。由于它的流行,所有主流浏览器都支持 Flash 插件。您可以使用<object>标签在网页中嵌入 Flash 视频;清单 3-2 展示了如何操作。

**清单 3-2。**使用<object>标签嵌入 Flash 视频

<object data="Media/Video1.swf" type="application/x-shockwave-flash" height="200" width="200">   <param name="movie" value="Media/Video1.swf"> </object>

这次的<object>标签播放的是 Flash 视频文件Video1.swftype属性指定 Flash 视频的 MIME 类型(application/x-shockwave-flash)。

嵌入 Silverlight 视频文件

微软在网页中显示媒体文件的解决方案是 Silverlight。Silverlight 被视为 Flash 的竞争对手,但因为它是一项相对较新的发明,所以在受欢迎程度和广泛使用方面落后于 Flash。然而,Silverlight 是一个灵活而强大的平台,可以使用。NET 工具,如 Visual Studio 和 Visual C#。您还可以使用 Expression Web 将现有媒体文件编码为特定于 Silverlight 的格式。清单 3-3 展示了如何使用 Silverlight 嵌入和播放视频。

***清单 3-3。*嵌入 Silverlight 媒体文件

<object data="data:application/x-silverlight-2" type="application/x-silverlight-2" width="300" height="300">   <param name="source" value="silverlightvideos/CleanTemplate.xap"/>   <param name="background" value="white" />   <param name="minRuntimeVersion" value="4.0.50401.0" />   <param name="autoUpgrade" value="true" />   <param name="enableHtmlAccess" value="true" />   <param name="enableGPUAcceleration" value="true" />   <param name="initparams" value='playerSettings =   <Playlist>     <DisplayTimeCode>false</DisplayTimeCode>     <EnableCachedComposition>true</EnableCachedComposition>     <EnableCaptions>true</EnableCaptions>     <EnableOffline>true</EnableOffline>     <EnablePopOut>true</EnablePopOut>     <StartMuted>false</StartMuted>     <StartWithPlaylistShowing>false</StartWithPlaylistShowing>     <StretchNonSquarePixels>NoStretch</StretchNonSquarePixels>     <Items>       <PlaylistItem>         <AudioCodec>WmaProfessional</AudioCodec>         <Description></Description>         <FileSize>1349539</FileSize>         <FrameRate>25</FrameRate>         <Height>360</Height>         <IsAdaptiveStreaming>false</IsAdaptiveStreaming>         <MediaSource>silverlightvideos/Video2.wmv</MediaSource>         <ThumbSource></ThumbSource>         <VideoCodec>VC1</VideoCodec>         <Width>640</Width>       </PlaylistItem>     </Items> </Playlist>'/> <a href="http://go2.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="https://go2.microsoft.com/fwlink/?LinkId=108181">

注意<object>标签现在是如何包含许多信息的。<param><Playlist>元素提供了大量的数据,比如 Silverlight 压缩输出文件的路径(.xap)和正在播放的视频的配置。

HTML5 音频和视频标签

在前面的章节中,您学习了 HTML5 之前的 web 应用如何使用<object>标签播放音频和视频文件。现在让我们把目光转向 HTML5,看看 HTML5 是如何原生支持音频和视频播放的。

HTML5 音频和视频支持分别以<audio><video>标记元素的形式出现。每个标签都有一组属性,可以用来配置文件的播放方式。此外,这些元素公开了可以使用 JavaScript 或 jQuery 编程的属性、方法和事件。以下部分详细讨论了<audio><video>元素。

播放音频

HTML5 <audio>标签允许你在网页中嵌入和播放音频文件。在其基本形式中,<audio>标签看起来像清单 3-4 。

***清单 3-4。*简单使用<audio>标签

`
**  **

`

src属性指向一个音频文件(Audio1.mp3),controls属性表示应该显示播放、暂停、音量等音频回放控件。图 3-1 显示了一个<audio>标签是如何在 IE9、Firefox、Chrome 和 Opera 中呈现的。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意并非所有的浏览器都支持所有的音频和视频格式。在本章的后面,你将学习如何在不同的浏览器中处理不同级别的支持。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

图 3-1。不同浏览器中的 <audio>元素

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-2。*IE9 中音频播放器的快捷菜单

如果你右击音频播放器,所有的浏览器都会显示快捷菜单(见图 3-2 )。您可以使用快捷菜单来控制音频回放。

<audio>标签还提供了一些有用的属性,让您可以微调音频文件的播放方式。默认情况下,当您使用<audio>运行页面时,音频文件不会播放,直到您点击播放按钮。如果您希望自动播放文件,您可以添加autoplay属性,如下所示:

<audio src="Audio1.mp3">

当用户阅读网页内容时,autoplay属性可以方便地播放背景声音。

默认情况下,音频文件完成后不会重播。要反复播放同一个文件,可以设置loop属性:

<audio src="Audio1.mp3">

当用户倾向于长时间停留在一个页面上,并且您希望不间断地播放背景音频时,loop属性非常有用。

还有一个preload属性控制浏览器如何加载音频文件。这个属性有三个可能的值:autometadatanoneauto值表示网页在浏览器中加载后,整个音频文件应该立即加载。metadata表示仅应加载元数据信息,如音频文件的长度。最后,none表示该文件根本不应该被加载。在这种情况下,文件只有在浏览器中播放时才会被载入。preload属性的默认值因浏览器而异。如果省略了preload属性,结果会因浏览器而异。以下标记显示了如何使用preload属性:

<audio src="Audio1.mp3">

使用preload属性,您可以控制在客户端下载多少媒体数据。例如,如果你在一个页面上显示一长串音频文件,将preload设置为auto可能会下载太多数据。在这种情况下,将preload设置为metadata会更有效。注意,如果autoplay属性存在,则preload被忽略。

播放视频

HTML5 <video>元素让你播放视频文件。它支持与<audio>标签相同的属性集,并提供更多的属性。这里显示了<video>的基本用法:

<video src="Video1.mp4">

src属性指向一个视频文件,而controls属性显示回放控制。图 3-3 显示了一个正在 IE9 中播放的视频文件。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-3。*IE9 中的<video>元素

除了autoplaylooppreload属性,您还可以将mutedposter属性用于<video>元素。muted属性表示正在播放的视频文件的音频输出是否应该静音。当您希望用户观看没有背景声音的视频时,可以使用此属性,如下所示:

<video src="Video1.mp4">

poster属性指向一个图像文件,该文件在下载视频时显示,或者在用户点击播放按钮之前显示。您可以使用poster显示视频的附加信息。这里有一个例子:

<video src="Video1.mp4">

图 3-4 显示了动作中的poster属性。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-4。*使用poster属性

除了到目前为止讨论的属性,你可以使用heightwidth属性来控制视频播放器的尺寸。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意 HTML5 <audio><video>元素并没有对最终用户隐藏媒体文件的位置。就像图像一样,您可以通过查看网页的 HTML 源文件并获取文件 URL,或者右键单击视频播放器并选择另存为菜单选项,轻松保存正在播放的媒体文件。

支持的音频和视频格式

在前面的章节中,您使用了<audio><video>标签来显示音频和视频文件。这些标签使用起来很简单,但是作为一个网页开发者,你需要注意一个灰色区域:音频和视频格式。尽管 HTML5 提供了对音频和视频播放的本地支持,但这种支持并不是在所有浏览器上都是一致的。不同的浏览器对可以播放的音频和视频文件格式不一致。比如 IE9 和 Chrome 播放 MP4 文件就可以了;但是如果你试图在 Firefox 中播放它们,你会得到错误“不支持视频格式或 MIME 类型”(见图 3-5 )。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-5。*火狐无法播放 MP4 文件。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意你可能想知道为什么不是所有的浏览器都支持所有流行的媒体格式。缺乏支持有各种原因,包括许可问题、专利问题、开放标准等等。对这些问题的详细讨论超出了本书的范围。

在研究浏览器及其支持的格式之前,有必要看一下 Web 上一些广泛使用的媒体格式,因为所有主流浏览器都支持其中一种或多种格式。表 3-1 列出了主流浏览器支持的文件格式。

注意表 3-1 中的 MIME 类型列。您必须确保您的 web 服务器具有文件扩展名和 MIME 类型的正确映射。如果这种映射不存在,web 服务器可能不会提供媒体文件,因此网页可能不会播放音频/视频。例如,在使用 Visual Studio 附带的开发 web 服务器时,您可能需要将清单 3-5 中所示的标记添加到web.config文件中,以便表 3-1 中提到的所有文件扩展名都能按预期工作。

***清单 3-5。*web.config 中添加 MIME)类型映射

<system.webServer>   <staticContent>       <mimeMap fileExtension=".mp4" mimeType="video/mp4" />       <mimeMap fileExtension=".ogg" mimeType="audio/ogg" />       <mimeMap fileExtension=".oga" mimeType="audio/ogg" />       <mimeMap fileExtension=".ogv" mimeType="video/ogg" />       <mimeMap fileExtension=".webm" mimeType="video/webm" />   </staticContent> </system.webServer>

正如你所看到的,<system.webServer><staticContent>子部分包含了几个<mimeMap>元素。每个<mimeMap>元素映射一个文件扩展名和它的 MIME 类型。

如果您使用的是 Internet 信息服务(IIS)的独立安装,而不是 Visual Studio 开发 web 服务器,也可以在 IIS 管理器中配置 MIME 类型。图 3-6 显示了 Windows 7 中相关的 IIS 管理器对话框。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-6。*IIS 中的 MIME 映射

面向 Asp.NET 开发者的 HTML5 编程教程(一) 多用途互联网邮件扩展(MIME)是非文本电子邮件附件的格式规范。尽管它最初是为电子邮件系统而设计的,但现在它被广泛用于 web 上来表示 Web 资源的内容类型。

现在您对各种媒体格式有了一些了解,让我们看看不同的浏览器是如何支持它们的。表 3-2 显示了来自表 3-1 的主流浏览器对媒体类型的支持。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意最好在这些浏览器的最新版本中测试一下表 3-2 中提到的媒体支持。该规范正在发展,所有的浏览器公司都在积极努力改进和标准化它们对媒体格式的支持。

实现回退机制

通过上一节的讨论,您可能已经意识到,在构建 Internet web 应用时,依靠浏览器来支持特定 MIME 类型的媒体文件是不现实的。另外,当你的目标浏览器未知时,你不能保证它支持 HTML5 <audio><video>标签。如果目标浏览器不支持 HTML5 音频和视频播放,某种形式的回退机制是必要的,以便为用户提供替代方案。

您需要为两种情况提供回退方案:

  • The target browser supports HTML 5 <audio> and <video> tags, but does not support specific MIME types.
  • The target browser does not support HTML 5 <audio> and <video> tags.

要处理这些情况,您可以分别使用以下回退机制:

  • Create media files with multiple file formats (MIME types).
  • Use flash or Silverlight as an alternate playback mode.

以下部分详细介绍了如何实现这些技术。

支持多种媒体格式

<audio><video>元素允许您指定多个媒体源。到目前为止,您已经使用这些标签的src属性来指定一个媒体文件,但是<audio><video>也可以使用嵌套的<source>元素来指定多个源文件。在运行时,根据支持的媒体类型,浏览器会选择适当的文件版本。清单 3-6 显示了一个<video>元素,它列出了三个来源。

***清单 3-6。*使用<source>元素

<video controls>   <source src="media/video1.mp4">

如清单 3-6 所示,每个<source>元素设置srctype属性。src属性指向一个视频文件,type属性表示文件的 MIME 类型。

使用<source>的缺点是您需要为每个音频或视频文件维护多种文件格式。这可能需要额外的媒体转换软件,从而增加项目的总成本。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意当你播放一个包含多个<source>元素的音频或视频文件时,浏览器使用的是哪种文件格式并不明显。一种快速简单的方法是在浏览器中右键单击<audio><video>元素,并从快捷菜单中选择另存为。另存为对话框显示正在播放的<source>元素的源文件名。

Flash 或 Silverlight 回退

如果您确定目标浏览器支持 HTML5,那么使用<source>元素的回退机制会工作得很好。然而,目标浏览器可能不理解 HTML5 <audio><video>元素。在这种情况下,您可以使用基于 Flash 或 Silverlight 的后备系统。清单 3-7 展示了一个使用 Flash 的例子。

***清单 3-7。*使用基于闪存的回退系统

<video controls>   <source src="media/video1.mp4">

现在,<video>元素中嵌套了一个<object>标签。这样,如果浏览器不理解<video>标签,它会跳到<object>标签并播放 Flash 视频文件。

如果您决定提供 Silverlight 回退,您需要使用<object>标签嵌入 Silverlight 媒体。清单 3-8 展示了如何做到这一点。

***清单 3-8。*使用基于 Sliverlight 的后备系统

<video controls>   <source src="media/video1.mp4">

在清单 3-8 中,Silverlight 媒体是使用<video>元素中的<object>标签嵌入的。如果浏览器遇到<video>标签但不支持它,浏览器会跳到<object>标签并播放 Silverlight 视频。

如果您不想提供 Flash、Silverlight 或其他后备,那么您可以简单地包含一些 HTML 标记来通知最终用户哪里出错了,而不是一个<object>标记。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意为了测试 Flash 或 Silverlight 回退方案,你需要一个不支持 HTML5 <audio><video>元素的浏览器版本。

用音频和视频 API 编程

到目前为止,您一直使用静态的<audio><video>元素来播放音频和视频文件。HTML5 还提供了一种使用 JavaScript 播放和控制媒体文件的编程方式。为了让您对可以配置的内容有所了解,表 3-3 列出了您可以使用的<audio><video> DOM 元素的属性、方法和事件。注意表 3-3 只列出了<audio><video>的常用成员。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意您可以在[www.w3schools.com](http://www.w3schools.com)浏览<audio><video>元素的所有可用成员。该网站还为其他 HTML5 标记、属性、方法和事件提供了很好的参考。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意在尝试播放媒体文件之前,检查浏览器是否支持<audio><video>标签总是一个好习惯。正如在第一章中所讨论的,你可以使用 Modernizr 库来实现这个目的。示例检查如下所示:

$(document).ready(function () {   if (!Modernizr.audio) {     alert("This browser doesn't support HTML5 audio!");   }   if (!Modernizr.video) {     alert("This browser doesn't support HTML5 video!");   } });

使用视频 API 创建自定义视频播放器

要查看<video>元素的属性、方法和事件,让我们在 ASP.NET MVC 应用中构建一个定制的视频播放器。视频播放器如图 3-7 中的所示。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-7。*一个定制的视频播放器

图 3-7 所示的自定义视频播放器提供了一个可以播放的视频文件的下拉列表。该列表驻留在 SQL Server 数据库中,并使用 jQuery $.ajax()方法获取。您可以使用播放和停止按钮来播放、暂停或停止视频。(单个按钮用于播放和暂停视频。)播放速度和音量可以使用相应的范围输入控件进行设置。一旦视频开始播放,总进度百分比(%)将与视频的总时长一起显示。播放器还包括一个海报,告诉用户从下拉列表中选择一个视频文件。

HTML5 标记

定制视频播放器的 HTML5 标记驻留在 MVC 视图(Index.aspx)中,如清单 3-9 中的所示。为了清楚起见,清单 3-9 只显示了视频播放器所需的标记,而不是完整的视图。

***清单 3-9。*自定义视频播放器的 HTML 标记

`


  Select Video To Play :

  

  

  

  

  
Progress :   

     

  
Playback Speed (1-5) :   

  
Volume (0-1) :   

`

这个 HTML5 标记由六个<div>元素组成。第一个<div>包含一个<select>元素,显示可以播放的视频列表。

第二个<div>元素包含一个 HTML5 <video>标签。<video>元素的id属性被设置为videoPlayer,其poster属性指向poster.jpg文件。当没有文件在videoPlayer中播放时,最初会显示由poster属性指示的图像。注意,<video>标签的src属性没有被设置,因为实际的视频 URL 是从下拉列表中选择的。即使标记设置了controls属性,如果您愿意,也可以跳过它,因为您以编程方式控制播放和暂停操作。

第三个<div>元素显示了视频的总时长和一个进度指示器,该指示器指定了视频已播放的百分比。

第四个<div>元素包含两个按钮:播放/暂停和停止。btnPlayPause在播放和暂停模式之间切换。

第五个和第六个<div>元素显示视频播放速率和音量的范围选择器。注意,代表范围选择器的两个<input>元素的type属性都被设置为range。(你将在第五章的中了解到 HTML5 中几种新的<input>类型。)这些范围选择器的minmax属性表示可以选择的最小值和最大值。step属性表示范围可以增加或减少的步长。

Index.aspx视图使用的 CSS 类驻留在应用的Site.css文件中。为了减少混乱,这里没有显示 CSS 类。

SQL Server 数据库和实体框架数据模型

该应用将可以播放的视频列表存储在 SQL Server Express 数据库中(VideoDb.mdf)。VideoDb由一个单独的表(Videos)组成,存储视频文件的标题和 URL。图 3-8 显示了服务器资源管理器中Videos表的模式。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

***图 3-8。*Videos的模式

要在代码级别表示Videos表并从该表中获取数据,您需要使用一个实体框架数据模型。数据模型驻留在Models文件夹中,看起来像图 3-9 。

面向 Asp.NET 开发者的 HTML5 编程教程(一)

**图 3-9。**实体框架Videos的数据模型类

Video数据模型类有三个属性——IdTitleUrl——对应于Videos表中的相应列。

获取视频播放列表

要在下拉列表中显示视频列表,您需要使用 jQuery 的$.ajax()方法从Videos表中获取数据。控制器类(VideoPlayerController)包含一个动作方法——GetPlayList()——返回一个Video对象列表。GetPlayList()方法和调用它的相关 jQuery 代码分别显示在清单 3-10 和清单 3-11 中。

清单 3-10。 GetPlayList()动作方法

public JsonResult GetPlayList() {     VideoDbEntities db=new VideoDbEntities();     var data = from items in db.Videos                 select items;     return Json(data.ToArray()); }

***清单 3-11。*使用$.ajax 调用GetPlayList()方法

`$.ajax({
    type: “POST”,
    url: ‘/VideoPlayer/GetPlayList’,
    dataType: ‘json’,
    contentType: “application/json; charset=utf-8”,
    success: OnSuccess,
    error: OnError
  });

function OnSuccess(playListItems) {
  for (var i = 0; i < playListItems.length; i++) {
    $(“#ddlPlayList”).append(“” +
      playListItems[i].Title +
      “”);
  }
}

function OnError(err) {
  alert(err.status + " - " + err.statusText);
}`

注意,GetPlayList()方法从Videos表中选择所有记录,并返回一个由Video对象组成的数组作为JsonResult。jQuery $.ajax()方法然后向GetPlayList()动作发出一个POST请求。成功函数OnSuccess()接收一个由Video对象组成的 JSON 数组。然后,OnSuccess()函数遍历这个 JSON 数组,每次迭代都使用append()方法将一个<option>元素添加到下拉列表中。视频文件的 URL 被分配给<option>元素的value属性,其标题显示在下拉列表中。

OnError()函数显示调用GetPlayList()方法时遇到的任何错误的信息。

播放、暂停和停止视频

您需要处理各种客户端事件,以使视频播放器正常工作。这些事件分为两类:

  • Events and other support elements such as play/pause and stop buttons, volume control, and drop-down list of <video> element.
  • event

第一类事件可以使用您在第二章中学到的 jQuery 事件处理语法来处理。清单 3-12 显示了这一类别中的各种事件处理程序。

***清单 3-12。*处理支持元素事件

`videoPlayer = $(“#videoPlayer”).get(0);

$(“#ddlPlayList”).change(function () {
  var extension = KaTeX parse error: Expected '}', got 'EOF' at end of input: …e(mime)) {     (“#btnPlayPause”).val(“Play”);
    videoPlayer.src =

(

t

h

i

s

)

.

v

a

l

(

)

;

    

(this).val();     

(this).val();    (“#btnPlayPause”).click();
  }
  else {
    alert(“Cannot play this video format!”);
  }
});

KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲btnPlayPause").…(this).val() == “Play”) {
    videoPlayer.playbackRate = KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲rngPlaybackRate…(“#btnStop”).click(function () {
  videoPlayer.pause();
  videoPlayer.currentTime = 0;
});

$(“#rngVolume”).change(function () {
  videoPlayer.volume = $(this).val();
});`

清单 3-12 中的代码在全局变量videoPlayer中存储了对<video> DOM 元素的引用。注意get()方法的使用,它在指定的索引处返回一个 DOM 元素。任何 jQuery 选择器都返回零个或多个匹配选择标准的元素的集合。您可以通过指定从零开始的索引,使用get()从集合中检索元素。在这种情况下,使用 ID 选择了<video>元素。自然,集合只有一个元素,因此index被指定为0

当下拉列表中的选择改变时,下拉列表的change事件处理程序负责播放视频。首先,它使用canPlayType()方法检查<video>元素是否可以播放选定的视频文件。canPlayType()方法接受媒体文件的 MIME 类型,如果该媒体类型可以播放,则返回true。如果<video>元素能够播放所选的视频文件,那么它的src属性被设置为所选视频文件的 URL,并且播放/暂停按钮的click事件以编程方式被触发。

播放/暂停按钮的click事件处理程序检查它自己的值。在处理程序内部,关键字this指的是被点击的 DOM 元素(即播放/暂停按钮),val()方法返回按钮的当前值。如果值为Play,则playbackRate属性被设置为在速度范围选择器中选择的值,并调用<video>元素的play()方法。这样,视频以选定的回放速度播放。如果值为Pause,则调用<video>元素的pause()方法,以便暂停视频播放。

停止按钮的click事件处理程序将currentTime属性设置为0以指示媒体文件的开始,并调用pause()方法。

音量范围选择器的change事件处理程序通过设置<video>元素的volume属性来改变视频播放的音量。

显示持续时间和进度

要显示所选视频文件的总长度及其播放进度,需要处理<video>元素的timeupdateloadmetadata事件。这些事件需要与以前有所不同。像clickchange这样的事件是标准的 HTML DOM 事件,并且原生包含在 jQuery 库中。然而,视频事件并非如此。因为<video>元素是 HTML5 中的新增元素,所以 jQuery 库没有对其事件的本地支持。因此,您需要连接事件处理程序,如清单 3-13 所示。

**清单 3-13。**使用 jQuery bind()方法连接事件

$(videoPlayer).bind("loadedmetadata", OnLoadedMetadata); $(videoPlayer).bind("timeupdate", OnTimeUpdate); $(videoPlayer).bind("play", OnPlay); $(videoPlayer).bind("pause", OnPause);

如您所见,jQuery 的bind()方法本质上是将事件与其处理程序绑定在一起。bind()方法的第一个参数是要处理的事件,第二个参数是事件处理函数。你可以在这里使用匿名函数,但是为了清晰起见清单 3-13 使用独立的 JavaScript 函数。

面向 Asp.NET 开发者的 HTML5 编程教程(一) 注意在撰写本文时,jQuery 还没有包含特定于 HTML5 的事件函数,比如playpause。这就是为什么这个例子使用了bind()方法。关于使用bind()方法进行事件连接的详细信息,请参见第二章。

您可能想知道为什么清单 3-13 中的会处理playpause事件。这样做是因为您还可以使用快捷菜单在视频播放器中播放和暂停视频。如果用户决定使用快捷菜单而不是播放/暂停按钮来播放或暂停视频,则播放/暂停按钮的功能会变得不同步。当使用任何一种方式(按钮或快捷菜单)播放或暂停视频时,都会引发playpause事件。通过处理这些事件,可以确保播放/暂停按钮始终反映播放器的正确状态。

事件处理函数OnLoadedMetadataOnTimeUpdateOnPlayOnPause如清单 3-14 所示。

***清单 3-14。*bind()方法中使用的事件处理函数

`function OnLoadedMetadata() {
  $(“#spanDuration”).html(“Duration : " + videoPlayer.duration.toFixed(1) + " seconds.”);
}

function OnTimeUpdate() {
  var percentage = Math.floor((videoPlayer.currentTime / videoPlayer.duration * 100));
  $(“#spanProgress”).html(percentage + " % ");
}

function OnPlay() {
  $(“#btnPlayPause”).val(“Pause”);
}

function OnPause() {
  $(“#btnPlayPause”).val(“Play”);
}`

加载正在播放的视频文件的元数据时,会引发loadmetadata事件。为了显示视频的持续时间,视频的元数据必须可用;因此,loadmetadata事件被用来在一个<span>元素中显示持续时间。duration属性返回以秒为单位的持续时间;为了正确显示,使用 JavaScript toFixed()方法将其转换为固定的十进制数。

每次视频的当前播放位置改变时,都会引发timeupdate事件。在<video>元素的currentTimeduration属性的帮助下,OnTimeUpdate()函数计算到目前为止视频播放的百分比。如此计算的进度显示在<span>元素中。

OnPlay()事件处理程序将播放/暂停按钮的文本设置为在视频开始播放时暂停。在同一行中,OnPause()事件处理程序设置播放/暂停按钮的文本在视频暂停时播放。

就这样!您的自定义视频播放器已准备就绪。您可以通过在Videos表中添加几个条目来测试播放器,然后通过从下拉列表中选择来运行这些文件。

总结

在 HTML5 之前,在网页中嵌入音频和视频文件需要第三方插件,如 Flash 和 Silverlight。开发人员使用<object>标签在网页中嵌入 Flash 或 Silverlight 媒体。HTML5 为分别使用<audio><video>元素播放音频和视频文件提供了原生支持。在撰写本文时,各种浏览器所支持的音频和视频格式还没有标准化,但是我们可以希望将来所有的浏览器都会同意一套通用的媒体格式。

因为不是所有的浏览器都支持 HTML5,所以您可能需要实现一个后备方案,这样如果浏览器不理解 HTML5 <audio><video>元素,Flash 或 Silverlight 播放器就会接管。使用与 jQuery 结合的<audio><video>标签,您可以开发数据库驱动的媒体目录或播放列表。

<audio><video>元素允许您播放现有的媒体文件。HTML5 <canvas>,下一章的主题,让你在浏览器中绘制形状、文本和图像,从而为构建图形丰富的网络应用提供了大量的可能性。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...