AJAX 的核心是 XMLHttpRequest 对象。AJAX 提供的用户体验机会取决于此对象在多个平台的大量浏览器上的可用性。自 2004 年以来已发生了很多事情,那一年,组件供应商首次开始展示 AJAX 应用程序,但在核心方面,如果不能使用 XMLHttpRequest 对象执行带外调用,就不可能有 AJAX。随着 AJAX 应用程序复杂性的提高,开发人员逐渐意识到要通过一种经济有效的方式构建新一代 Web 应用程序,只靠简单的脚本驱动的带外调用是不够的。因此,对功能更加强大的工具集的需求不断增长,开发人员希望这些工具能够将 AJAX 功能添加到页面和应用程序,同时使用与传统的 ASP.NET 相同的开发模式。因此,简言之,要构建 AJAX 站点,开发人员不仅需要能够简单地调用 XMLHttpRequest 对象来提取数据,能够手动制作 JavaScript 功能来操作文档对象模型 (DOM),还需要一些其他功能。在本月的专栏中,我将介绍一种针对利用 ASP.NET 部分呈现引擎的 AJAX 的实用方法。稍后您将看到,AJAX 需要在应用程序性能和开发人员效率之间寻求平衡。实际的 AJAX 站点并不完全是使用部分呈现或 XMLHttpRequest 对象的手动脚本构建的,它们需要的是功能强大的混合技术,这些技术通常可以通过自定义控件很好地合成。
带有菜单的页面 AJAX 的主要功用是最小化要重新加载的完整页面数目。部分呈现和手动脚本驱动调用都允许您提取服务器端数据,并避免整页刷新。对于许多内容类型而言,后端服务和 DOM 操作可能已经足够了。但如果您必须支持导航,会怎样呢?传统的超链接破坏了 AJAX 的神奇功能,它会告知浏览器请求另一个 URL。结果,当前页面被冻结,直到下载完新的 HTML 块。当新数据到达时,该页面关闭,然后完全重绘浏览器的客户端。位于母版页上的顶级链接可向用户指示站点的不同区域,这些链接可能确实会像传统超链接一样实现。在这种情况下,重新加载整个页面可能是可以接受的,但具体取决于用户的期望。每次构建菜单时,都需要选择如何处理用户单击。您可以为每个菜单项分配一个 URL,也可以只是回发到同一页面。从 AJAX 角度看,您是在选择关闭当前页面、加载全新页面还是从服务器异步加载某些新内容。请看以下代码片段,它显示了 ASP.NET 菜单控件的片段: 复制代码
“产品”菜单项的第一个 MenuItem 子元素起到的是 NavigateUrl 属性的作用。此属性可获取或设置单击菜单项时 URL 导航到的目标位置。第二个 MenuItem 元素起到的是 Value 属性的作用。Value 属性用于存储有关菜单项的其他数据,将被传递给 MenuItem 的回发事件。同一级别的每个菜单项都必须拥有唯一的 Value 属性值。当未指定显式导航 URL 时,单击菜单项会导致传统的回发。在服务器上,您只需处理 MenuItemClick 事件和 Value 属性的内容。显然,如果您选择使用 Value 属性的方法,就可以使用 AJAX 技术并避免整页重新载入。此类型页面的整体模型是一个单页界面。单页界面减少了重新加载的数量并消除了闪烁,因此可减轻用户界面的负担。然而,单页界面也意味着您的应用程序使用的 URL 区别很小,从而使来自搜索引擎的支持减弱。单页界面也意味着开发团队需要编写的页面减少,但页面内容更加丰富。此类方法还可以减少团队内部的并行操作。导航 URL 当菜单将用户引入全新页面时,实际上您不需要使用“菜单”控件来实现解决方案。理论上,有超链接列表就已经足够了。虽然届时会有许多 DHTML 和 AJAX 菜单框架可用,但到最后,它们的动画、图形和提供的预定义外观会不同。从功能上讲,这些菜单只是超链接的集合,这些超链接由浏览器通过非 AJAX 方式本地处理。通常,总页数多达数百的网站可能是针对少数入口页设置的,这些入口页随后会将用户引入不同的子网站。因此,主页只需要指向这些子网站的链接。在这种情况下,就需要导航,而不必非得用 AJAX。但是如果需要将内容拉至当前显示的页面,又该如何呢?您要如何组织此内容才能最大程度地提高应用程序的性能和团队的工作效率?
异步回发上个月,我演示了如何使用 Windows Communication Foundation (WCF) 服务将原始数据或 HTML 返回到客户端。两种解决方案都各有优缺点。发送原始数据可优化带宽,但需要您使用 JavaScript 在此客户端上实现一些 DOM 操作逻辑。发送服务器生成的 HTML 会增加移动的数据量,但它允许您在服务器上维护大多数呈现逻辑。这两种方法均属于所谓的“真正的”AJAX 解决方案类别,在此类别中基于双层模型 — Web 浏览器和服务层明确设计了应用程序。涉及用户界面的任何状态和逻辑均由客户端维护并控制;不需要任何视图状态或回发。若要返回只读标记,则服务器生成的 HTML 最有用。如果您需要返回静态数据网格,或返回包含所选客户或发票的一些相关信息的面板,它将非常适合。如果您需要打开一个充满控件的交互面板,并且这些控件会触发事件并需要处理程序,它的吸引力就小得多了。在纯 AJAX 方法中,显示的标记(在客户端生成或在服务器上生成)必须包含 JavaScript 函数调用。上个月,我使用服务实现了 HTML 消息模式和浏览器端模板模式。但您可能已经注意到,我的示例并非真正具有交互效果。事实证明这两种方法适用于部分情况,而非全部。我的示例服务返回了股票报价,但最终网格无法分页。例如,要支持分页,我必须插入指向 JavaScript 功能的超链接,然后确保下载了引用的 JavaScript。
菜单和部分呈现图 1 显示了带有顶级菜单的示例页,允许用户在应用程序功能集中导航。此菜单已使用 ASP.NET 菜单控件创建,如图 2 所示。您可以看到,所有菜单项都没有指定 NavigateUrl 属性,这个属性会将每个菜单项指向一个物理 URL,这就可能会指向一个完全不同的页面。指定 Value 属性后,每当用户选择任一菜单项后,都会发生回发,并且 MenuItemClick 事件将被引发至该页面: