Dojo高级传输层 io 包中的dojo.iframe
在丰富的Dojo框架库中,Dojo Core 提供了一个 io 包,由两个对象组成:dojo.io.iframe 和 dojo.io.script,Dojo 的官方说明把他们描述成“高级传输层(advanced ajax transport layer)”。使用 dojo.io.iframe 同样可以跟服务器交互,但是它的实现思路是有别于 XHR 对象的。dojo.io.iframe 的使用方式、参数与 xhrGet 非常相似。如xhrGet 中的from,url,handleAs,load 等参数在这里也存在,但有一处不同的是 method,method 表示 dojo.io.iframe 将以何种 HTTP Method 来发送请求。
疑问:
- dojo.io.iframe 是如何工作的呢?
- 除了 XHR 对象之外还有什么方法可以实现表单的异步提交?
其实这一切都很简单,dojo.io.iframe 首先会创建一个隐藏的 iframe 并插入到父页面的最后,然后设置此 iframe 的 src 属性为dojo-module-path/resources/blank.html(dojo-module-path 指 dojo 包所在的目录),iframe 页面的 onload 事件的处理函数被设置为父窗体的回调函数。接下来就是在 iframe 页面中发送请求,并接收服务器的响应。当 iframe 接收到服务器的反馈并加载完之后,父窗体的回调函数即被调用。
疑问:
那么dojo.io.iframe有哪些函数呢?
- create(fname, onloadstr, uri) 用来在页面中创建 iframe。
参数 | 类型 | 描述 |
---|---|---|
fname | String |
所创建 iframe 的名字,setSrc 和 doc 函数据此引用创建的 iframe |
onloadstr | String |
表示 iframe 加载完成后执行的回调函数 |
uri | String |
iframe 请求的资源,当 uri 为空时,将加载dojo-module-path/resources/blank.html |
- doc(iframeNode) 获取指定的 iframe 页面的 DOM 根节点,有了它可以对 iframe 页面进行任意的操作。
参数 | 类型 | 描述 |
---|---|---|
iframeNode | undefined |
- setSrc(iframe, src, replace) 设置指定的 iframe 的 src 属性,这将导致 iframe 页面重新加载。
参数 | 类型 | 描述 |
---|---|---|
iframe | undefined | |
src | undefined | |
replace | undefined |
dojo.io.iframe 采用了不同的思路实现了“异步”发送请求,但是 dojo.io.iframe 使用并不多,因为当页面中多处需要异步通信时,在页面中创建很多的 iframe 并不是好的注意。在能使用 xhr 框架的地方尽量使用 xhr 框架,唯一值得使用 iframe 的地方是发送文件。
疑问:
来个例子呗?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>dojo.iframe笔记 --http://www.cnblogs.com/f-ye</title> <!-- import css --> <link href="/Dojoroot/dojo/resources/dojo.css" rel="stylesheet" type="text/css" /> <link href="/Dojoroot/dijit/themes/soria/soria.css" rel="stylesheet" type="text/css" /> <!-- import js --> <script type="text/javascript" src="/Dojoroot/dojo/dojo.js" data-dojo-config="parseOnLoad: false, async:true"></script> </head> <body class="soria"> <div> <label>教程文件</label> <form id="uploadForm" method="post" enctype="multipart/form-data"> <input id="courseFile" name="courseFile" type="file" /> </form> </div> <div> <input type="button" value="上传" onclick="DoUpload()" /> </div> <script type="text/javascript"> require(["dojo/io/iframe"]); function DoUpload() { dojo.io.iframe.send({ contentType:"multipart/form-data", url: "/teach/upload", handleAs: "text", load: function (result) { alert(result); }, error: function (err) { alert(result); }, form: "uploadForm" }); } </script> </body> </html>
需要注意的一点是 handleAs 参数,dojo.io.iframe 一般使用 html,因为在 iframe 中存的其实是另一个 HTML 页面。如果 handleAs 设置为其他值,像 json,text 等,则在服务器端须使用 <textarea></textarea> 把要返回的数据包装起来,比如 hellow, world 要被包装成 <textarea>hello,world</textarea>,所以最后存在 iframe 中的是一个文本域(textarea),这个文本域包含了从服务器端返回的数据。这么做的原因很简单,就是为了保持从服务器返回的数据“一成不变”,因为任何字符数据都可以“安全的”放在 HTML 页面的文本域中。想像一下,我们是不是可以在文本域中输入各种字符! dojo.io.iframe 会对 textarea 包装的数据进行处理:首先把 textarea 标签去掉,然后把数据转换为 handleAs 指定的类型传递给 handle 中设置的回调函数。
疑问:
那服务端怎么写呢?(介绍在MVC3中的写法)
public ActionResult Upload(FormCollection form) { var result = "没有文件"; if (Request.Files.Count > 0) { var file = Request.Files[0]; if (file.ContentLength == 0) { result = "文件为空"; } else { file.SaveAs(Server.MapPath("~/UpLoad/") + file.FileName); result = "成功"; } } return Content(String.Format("<textarea>{0}</textarea>", result)); }
dojo.io.iframe 采用了不同的思路实现了“异步”发送请求,但是 dojo.io.iframe 使用并不多,因为当页面中多处需要异步通信时,在页面中创建很多的 iframe 并不是好的注意。在能使用 xhr 框架的地方尽量使用 xhr 框架,唯一值得使用 iframe 的地方是发送文件。