16.6 关于Ajax技术的注意事项
使用JavaScript来实现客户端/服务器的通信,极大地扩展了JavaScript语言的功能。但是,使用这种强大功能的同时,也带来了一些需要注意的问题。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)在这一小节中,前两个问题将分别讨论使用Ajax技术时同源策略的问题,以及使用XMLHttpRequest对象时所带来的ActiveX控件问题。第三个问题将讨论Ajax的可用性问题,即Ajax技术改变了页面中的某些方面,并如何解决这些问题。
16.6.1 同源策略早在Netscape Navigator 2.0浏览器时代,JavaScript代码就不能访问非同源的脚本或者页面。这是浏览器所遵循的一个重要的安全措施。否则,一些恶意代码的编写者就能在任何地方执行恶意的代码。同源策略指的是,仅当两个页面的协议(HTTP)、端口号(默认时为80端口)和主机名相同时,这两个页面才是同源的。
例如,下面这两个页面:
● 页面1的位置为http://www.site.com/folder/mypage1.htm
● 页面2的位置为http://www.site.com/folder10/mypage2.htm
根据同源策略的要求,这两个页面是同源的。因为这两个页面具有相同的主机名(www.site.com),使用了相同的协议(HTTP),并访问了相同的端口(这两个页面并没有声明端口,因此使用的是默认的80端口)。由于这两个页面是同源的,因此一个页面中的JavaScript将可以访问另一个页面。
再如下面的两个页面:
● 页面1的位置为http://www.site.com/folder/mypage1.htm
● 页面2的位置为https://www.site.com/folder/mypage2.htm
显然,这两个页面并不是同源的。虽然这两个页面的主机名和端口号是相同的,但是却使用了不同的协议。页面1使用的是HTTP协议,而页面2使用的是HTTPS协议。这一差异使得浏览器将这两个页面视为两个不同的源。因此,其中一个页面中的JavaScript将无法访问另一个页面。
那么,这与Ajax技术有什么关系呢?由于Ajax技术中大量使用了JavaScript,因此同源策略几乎影响到Ajax的每一方面。例如,由于同源策略的限制,XMLHttpRequest对象将无法访问任何非同源的文件。但是,我们可以采用一种很简单方式来解决这一问题,即使用一个同源的页面作为代理(proxy),通过该代理来获取另一个非同源服务器上的数据。同源策略同样影响到使用frame/iframe方式来实现的Ajax技术,即使两个页面位于同一个框架集中,但是如果这两个页面不同源的话,JavaScript将无法在这两个页面之间实现交互。
16.6.2 ActiveX对Ajax的影响XMLHttpRequest对象的一个弊端在于它是一个ActiveX控件,因此只有在Windows系统的IE浏览器中才可以使用XMLHttpRequest对象。尽管IE浏览器是当前市场占有率最高的浏览器,而且它的市场占有率短期内似乎不会发生什么改变。但是,由于在过去几年中,围绕 ActiveX控件产生了很多的安全性问题,特别是很多恶意广告软件和间谍软件通过用户计算机对ActiveX控件的信赖而安装在用户的计算机中。因此,ActiveX控件的使用对用户的计算机安全造成了一定的隐患。
由于人们对安全性问题越来越重视,Microsoft采取了一些措施,以严格限制对ActiveX控件或插件对象的访问,这样不但使浏览器变得更加安全,还有效地避免了恶意的攻击。但是这样一来,如果用户完全禁用了ActiveX控件,或者你的站点被标记为某一特定的安全区域,就可能使得ActiveX控件对象无法创建,从而导致基于XMLHttpRequest对象的Ajax程序无法正常工作。
16.6.3 可用性问题Ajax技术打破了传统Web应用程序和Web页面的模式。Ajax允许创建类似于普通桌面应用程序的Web应用,而不是充满了Web味(webbish)的页面。但是,Ajax技术也存在一定的缺点,Internet已经存在并发展了很多年,某些用户可能已经习惯了传统的Web页面。
因此,我们需要确保用户能够使用我们的Web页面,并以他们熟悉的方式来访问页面,在使用Ajax技术时,不应给用户造成挫折感。
1. 浏览器的Back按钮浏览器的Back和Forward按钮是用户使用Web的常用功能。在本章前面的内容中,我们已经讨论过,在使用XMLHttpRequest对象发起请求时,浏览器将不会在其历史记录中保存由XMLHttpRequest对象发起的浏览记录,这将使得浏览器的Back和Forward按钮失效。为此,我们创建了一个使用隐藏iframe技术实现的Ajax表单,以确保浏览器的Back和Forward按钮的功能继续有效。
但是,使用隐藏框架技术仍然存在一定的局限。在IE浏览器中,使用隐藏frame/iframe技术并没有什么问题。IE浏览器将记录每一个向服务器发起的请求,因此可以使用浏览器的Back和Forward按钮在历史记录中前进或后退。但是对于其他的浏览器来说,情况并非如此,在其他的浏览器中则可能存在一些值得注意的怪癖。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)例如Firefox浏览器,如果我们直接在HTML页面中添加iframe标记,则Firefox浏览器也将在其历史记录中保存每一个请求的记录。但是在早期版本的Firefox浏览器中,如果我们使用DOM方法动态地将iframe标记添加到HTML页面中,Firefox浏览器将不会记录由iframe发起请求的浏览记录。
另外,我们必须注意Safari浏览器。Safari浏览器并不记录由iframe发起的请求。对于Safari浏览器,必须使用一个传统的框架集来实现Ajax技术,以便Safari浏览器能够记录浏览的历史记录。对于Safari浏览器来说,隐藏的框架页同样可以实现iframe的功能,只不过使用框架集来代替了iframe。
2. 使用Ajax来处理延迟与常见的应用程序一样,Web程序也可以通过用户界面(UI)来提示用户系统真正执行某种任务。例如,当用户单击了某一个超链接时,一个跳动的动画将开始运行,在Windows系统中,一个沙漏图标将出现在鼠标指针的旁边,并且通常在状态栏中显示浏览器正在加载页面的信息。
这正是Ajax技术特别是XMLHttpRequest对象的另一个典型应用场景。而且这一功能非常容易实现:只需简单地添加一个UI元素以告诉用户某个任务正在运行,并在该任务完成之后将该UI元素移除即可。例如下面的代码:
function requestComplete(sResponseText)
{
//do something with the data here
document.getElementById("divLoading").style.display = "none";
}
var myRequest = new HttpRequest("http://localhost/myfile.txt",
requestComplete);
document.getElementById("divLoading").style.display = "block";//show that
we’re loading
myRequest.send();
上面的代码使用了前面创建的HttpRequest类来发起一个对myfile.txt文件的请求。在发送请求之前,通过document.getElementById("divLoading")方法获取id号为divLoading的div/元素。该div/元素将告诉用户数据正在加载中。当请求已经完成时,则将div/元素隐藏,以便让用户知道数据加载过程已经完成。
在数据加载过程中,应该向用户显示相应的提示信息,以便用户知道应用程序正在按他的请求执行某些操作。否则,当用户单击了超链接之后却没有任何及时的反应,用户可能就会怀疑我们的应用程序是否在正常工作。
3. 当Ajax失败时预留退路在理想情况下,我们所编写的代码每次都能正常运行。但是遗憾的是,我们不得不面对这样的事实,使用Ajax技术的页面并不能总是为我们带来Ajax的好处,用户的浏览器可能禁用了JavaScript,从而导致带有Ajax功能的页面执行失败。
解决这个问题的唯一办法是:创建一个老式的Web页面,并使用老式的表单、超链接和其他HTML元素。然后,关闭这些HTML元素的默认行为,并使用JavaScript来添加相应的Ajax功能。例如,对于下面这个超链接:
a href="http://www.wrox.com" title="Wrox Publishing"Wrox Publishing/a
这是一个普通得不能再普通的超链接。当用户单击该超链接时,将把用户导航到http://www.wrox.com页面。通过使用JavaScript,可以覆盖(override)超链接的默认行为,并替换为我们所需要的功能。
a href="http://www.wrox.com" title="Wrox Publishing"
onclick="return false;"Wrox Publishing/a
实现这个功能的关键在于从超链接的onclick事件处理器中返回一个false值。我们可以在该事件处理器中执行任何我们所需要的代码,只需最后返回一个false值即可。返回的false值将告诉浏览器当用户单击超链接时不执行任何默认的动作。如果用户的浏览器禁用了JavaScript功能,则onclick事件处理器将被忽略,超链接将恢复到正常的行为。
作为一个经验法则,最好先创建Web页面,再在页面中添加相应的Ajax功能。