【转】退而求其次的选择1:使用IFrame发送请求《深入理解Ajax:基于JavaScript的RIA开发 》

来源:互联网 发布:快3遗漏数据分析 编辑:程序博客网 时间:2024/05/29 04:44

IFrames为异步调用提供了一个合适的传输途径,因为它们可以在不使整个页面重新装载的基础上载入新内容,而新的IFrame元素则可以通过JavaScript创建。IFrame最好的属性之一是表单可以将其作为目标,从而只需重载IFrame而不用对整个页面进行重载;该方法可以通过POST类型请求将大量数据发送给服务器。

在使用IFrame作为传输方法时,其中的一个难点是载入的页面必须是HTML格式的,并且在载入完成时,需要通过JavaScript的onload事件句柄来告诉其父文档。这就使得基于IFrames发出的所有请求所针对的页面都必须是针对IFrame请求设计的(其代码无法像在XMLHttpRequest方法中那样获取一个XML文件)。

注意,使用IFrames还有许多其他限制:

·  只支持异步请求;

·  需要修改服务器端页面;

·  会在浏览器的历史中加上虚构的项;

·  在某些浏览器上,会使后退、前进按钮的行为变得不确定;

·  在不同浏览器中的实现有巨大的不同,特别是在老版本的浏览器中。

IFrame和XMLHttpRequest相比也有一个优点,即可以用来完成文件上传。由于浏览器的安全限制,只有诸如单击表单的用户操作可以与用户机器上的文件交互。可以仅对文件上传使用目标为一个IFrame的表单,它不涉及常规的表单POST操作和页面重载周期。不过,这不是针对文件上传使用IFrame,而对其他Ajax请求则使用XMLHttpRequest的理由。除非发起的是远程脚本风格的Ajax请求(这将在第3章中讲述),对于IFrame的限制,会使所有Ajax开发项目的工作量大大增加。

1  创建一个隐藏IFrame

为了最大程度上与老版本浏览器兼容,可以在HTML中添加IFrame并将其大小设置为0x0(不能仅是隐藏它,否则有些浏览器将不会载入它)。不过该方法的灵活性并不好,因此应该动态地创建这个帧。并非所有老版本的浏览器都支持document.createElement方法,但不支持该方法的浏览器通常也不具备在载入数据时所需的其他动态能力,因此对于它们最好是提供一个静态HTML版本的页面。在下面的例子中,使用innerHTML创建了这个IFrame,因为它比使用DOM方法更简单。注意,这里也使用了document.createElement方法,用来添加div元素:

2  创建一个表单

如果要发起GET请求,只需修改IFrames中src属性的值,但进行POST请求时则需要使用一个目标表单。GET方法并不是Ajax请求的良好解决方案,主要有两个原因:它能够发送的数据是有限的(具体的数据量限制取决于浏览器),GET请求会被代理服务器缓存且/或预载入,因此决不要用它来执行诸如数据库更新之类的操作。

在IFrame中使用一个表单是很简单的。只要设置表单的target属性即可,当提交该表单时,其结果就将在该IFrame中载入。以下例子创建了我们的表单,并将其target属性设置为在第2.5.1节中创建的IFrame:

3  从载入的内容向原始文档发送数据

要知道IFrame的内容已经载入的唯一方法是在内容页上运行一些JavaScript代码,以提示IFrame所嵌入的父页面。完成该任务的最简单方法是设置载入文档的onload事件句柄。这一限制意味着使用IFrame不能像使用XMLHttpRequest那样载入任意的内容。不过,当某个页面已被作为Ajax网关时,该方法仍然是很有效的。以下就是一个onload事件句柄的实例:

4  基于IFrame的Ajax完整实例

一个完整的基于IFrame的Ajax实例中的请求包含两个部分内容。第一部分是客户端代码,用来创建IFrame和表单;第二部分是服务器端代码,它负责准备数据,并通过父文档的onload事件句柄将其发送回去。

本例的第1部分(程序清单2-5所示)是位于一个简单HTML文件中的JavaScript代码。该页面用于测试;回调函数只是在警告对话框中显示出结果。该例子的第2部分(程序清单2-6所示)是一个简单的PHP脚本,它负责从POST请求中获取数据,并将其回送给父文档。为实现一个实际有效的系统,可能需要在表单中添加一些其他变量,以告诉PHP代码如何处理上传的数据,或者可以在脚本中直接加入业务逻辑,并对要实现的每个任务都设置一个不同的目标页。

程序清单2-5  使用IFrame发送一个Ajax请求

程序清单2-5中包含3个函数:

·  createRemotingDiv  用来设置IFrame。

·  sendRequest  用来发起Ajax请求。

·  test  发起Ajax请求。test函数在页面的HTML代码中与一个链接绑定在一起。用户点击该链接,将启动一个Ajax请求。

函数createRemotingDiv中所包含的代码在前面已经描述过了,它包括的代码用来创建隐藏IFrame以及将向其提交信息的表单。在表单创建完后,其目标将是新创建的IFrame,用表单提交代替当前页面的重载。开发时,经常在调试过程中显示IFrame,这是很有效的,因为可以看到调用的页面所生成的输出。要实现该目标,可以将第8行修改为“width:200;height:200”。

函数sendRequest用来发起Ajax请求。其参数包括请求将发向的URL、发送给服务器的payload,以及请求完成时将执行的回调函数。该函数使用createRemotingDiv来配置这一过程。然后sendRequest将更新IFrame表单的操作,把payload值填充到表单中,使用IFrame提交该表单。当在IFrame中载入了新页面时,新文档将通过JavaScript的onload句柄调用已传给sendRequest方法的回调函数。这个处理POST表单的PHP页面,以及创建onload句柄的JavaScript代码如程序清单2-6所示。

程序清单2-6  处理基于IFrame的Ajax请求的PHP服务器端页面

在服务器端,该表单将被处理,并将以HTML页面的形式创建输出。添加新数据的最简单方法是生成包含新数据的JavaScript。在这里,我们只是通过为result变量赋值的方法,将数据回显给客户端。通常,在此会运行服务器端代码,或者输出一个字符(就像本例这样),或者添加将在父文档中执行的新JavaScript代码。父文档的回调函数是在body标签的onload事件句柄中定义的。

 

注意:以上JS代码在插入的时候可能自动添加了mce字样,调试时请自行去除~

原创粉丝点击