使用javascript来实现客户端/服务器的通信,极大地扩展了javascript语言的功能。但是,使用这种强大功能的同时,也带来了一些需要注意的问题。
在这一小节中,前两个问题将分别讨论使用ajax技术时“同源策略”的问题,以及使用xmlhttprequest对象时所带来的activex控件问题。第三个问题将讨论ajax的可用性问题,即ajax技术改变了页面中的某些方面,并如何解决这些问题。
早在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将无法在这两个页面之间实现交互。
xmlhttprequest对象的一个弊端在于它是一个activex控件,因此只有在windows系统的ie浏览器中才可以使用xmlhttprequest对象。尽管ie浏览器是当前市场占有率最高的浏览器,而且它的市场占有率短期内似乎不会发生什么改变。但是,由于在过去几年中,围绕 activex控件产生了很多的安全性问题,特别是很多恶意广告软件和间谍软件通过用户计算机对activex控件的信赖而安装在用户的计算机中。因此,activex控件的使用对用户的计算机安全造成了一定的隐患。
由于人们对安全性问题越来越重视,microsoft采取了一些措施,以严格限制对activex控件或插件对象的访问,这样不但使浏览器变得更加安全,还有效地避免了恶意的攻击。但是这样一来,如果用户完全禁用了activex控件,或者你的站点被标记为某一特定的安全区域,就可能使得activex控件对象无法创建,从而导致基于xmlhttprequest对象的ajax程序无法正常工作。
ajax技术打破了传统web应用程序和web页面的模式。ajax允许创建类似于普通桌面应用程序的web应用,而不是充满了web味(webbish)的页面。但是,ajax技术也存在一定的缺点,internet已经存在并发展了很多年,某些用户可能已经习惯了传统的web页面。
因此,我们需要确保用户能够使用我们的web页面,并以他们熟悉的方式来访问页面,在使用ajax技术时,不应给用户造成挫折感。
浏览器的back和forward按钮是用户使用web的常用功能。在本章前面的内容中,我们已经讨论过,在使用xmlhttprequest对象发起请求时,浏览器将不会在其历史记录中保存由xmlhttprequest对象发起的浏览记录,这将使得浏览器的back和forward按钮失效。为此,我们创建了一个使用隐藏iframe技术实现的ajax表单,以确保浏览器的back和forward按钮的功能继续有效。
但是,使用隐藏框架技术仍然存在一定的局限。在ie浏览器中,使用隐藏frame/iframe技术并没有什么问题。ie浏览器将记录每一个向服务器发起的请求,因此可以使用浏览器的back和forward按钮在历史记录中前进或后退。但是对于其他的浏览器来说,情况并非如此,在其他的浏览器中则可能存在一些值得注意的怪癖。
例如firefox浏览器,如果我们直接在html页面中添加<iframe>标记,则firefox浏览器也将在其历史记录中保存每一个请求的记录。但是在早期版本的firefox浏览器中,如果我们使用dom方法动态地将<iframe>标记添加到html页面中,firefox浏览器将不会记录由iframe发起请求的浏览记录。
另外,我们必须注意safari浏览器。safari浏览器并不记录由iframe发起的请求。对于safari浏览器,必须使用一个传统的框架集来实现ajax技术,以便safari浏览器能够记录浏览的历史记录。对于safari浏览器来说,隐藏的框架页同样可以实现iframe的功能,只不过使用框架集来代替了iframe。
与常见的应用程序一样,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/>元素隐藏,以便让用户知道数据加载过程已经完成。
在数据加载过程中,应该向用户显示相应的提示信息,以便用户知道应用程序正在按他的请求执行某些操作。否则,当用户单击了超链接之后却没有任何及时的反应,用户可能就会怀疑我们的应用程序是否在正常工作。
在理想情况下,我们所编写的代码每次都能正常运行。但是遗憾的是,我们不得不面对这样的事实,使用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功能。
新闻热点
疑难解答
图片精选