隐藏框架只是异步交互的载体,它仅负责信息的传输,而交互的核心应该是一种信息处理机制,这样处理机制就是回调函数。
所谓回调函数,就是客户端页面中的一个普通函数,但是该函数是在服务器端被调用,并负责处理服务器端响应的信息。
在异步交互过程中,经常需要信息的双向交互,而不仅仅是接收服务器端的信息。下面示例演示如何把客户端的信息传递给服务器端,同时让服务器准确接收客户端信息。本例初步展现了异步交互中请求和响应的完整过程,其中回调函数的处理又是整个案例的焦点。
1) 构建一个框架集(index.htm)。
<html>
<head>
<title></title>
</head>
<frameset rows="*,0">
<frame scr="main.htm" name="main" />
<frame src="black.htm" name="server" />
</frameset>
<noframes>您的浏览器不支持框架集,请升级浏览器版本!</nodrames>
</html>
本文档框架集由上下两个框架组成,第二个框架高度为 0,但是不要设置为 0 像素高,因为在一些老版本的浏览器中会依然显示。这两个框架的分工如下:
使用 <noframes> 标签兼容老版本浏览器,使用户体验更友好。
2) 在默认状态下,框架集中第二个框架加载一个空白页面(black.htm),第一个框架中加载与客户进行交互的页面(main.htm)。
第一个框架中主要包含两个函数:一个是响应用户操作的回调函数,另一个是向服务器发送请求的事件处理函数。
<html>
<body>
<title>与客户交互页面</title>
<script>
function request () { //向服务器发送的异步请求函数
var user = document.getElementById ("user"); //获取用户输入的用户名
var pass = document.getElementById ("pass"); //获取用户输入的密码
var s = "user=" + user.value + "&pass=" + pass.value; //构造查询字符串
parent.frames[1].location.href = "server.htm?" + s;
//为框架集中第二个框架加载服务器端请求文件,,并附加查询字符串,传送客户端信息,以实现异步信息的双向交互
}
function callback (b, n) { //异步交互的回调函数
if (b) { //如果参数b为真,说明输入信息正确
//获取第一个框架中body元素的引用指针,以实现向其中插入信息
var e = document.getElementsByTagName ("body") [o];
//在交互页面中插入新的交互信息
e.innerHTML = "<h1>" + n + "</h1><p>你好,欢迎登录站点</p>";
} else { //如果参数b为假,说明输入信息不正确
console.log("您输入的用户名或密码有误,请重新输入"); //提示重新输入信息
var user = parent.frames[0].document.getElementById ("user"); //获取第一个框架中的用户名文本框
var pass = parent.frames[0].document.getElementById ("pass"); //获取第一个框架中的密码文本框
user.value = ""; //清空用户名文本框中的值
pass.value = ""; //清空密码文本框中的值
}
}
window.load = function () { //页面初始化处理函数
var b = document.getElementById ("submit"); //获取【提交】按钮
b.onclick = request; //绑定鼠标单击事件处理函数
}
</script>
</head>
<body>
<h1>用户登录</h1>
用户名 <input name="" id="user" type="text"><br /><br />
密码 <input name="" id="pass" type="password"><br /><br />
<input name="submit" type="button" id="submit" value="提交" />
</body>
</html>
由于回调函数是在服务器端文件中被调用的,所以对象作用域的范围就发生了变化,此时应该指明它的框架集和框架名或序号,否则在页面操作中会找不到指定的元素。
3) 在服务器端的文件中设计响应处理函数,该函数将分解 HTTP 传递过来的 URL 信息,获取查询字符串,并根据查询的字符串中的用户名和密码判断当前输入的信息是否正确,并决定具体响应的信息。
<html>
<head>
<title>服务器端响应和处理页面</title>
<script>
window.onload = function () { //服务器响应处理函数,当该页面被请求加载时触发
var query = location.search.substring (1); //获取URL中所包含的查询字符串
var a = query.split ("&"); //劈开查询字符串为数组
var o = {}; //临时对象直接量
for (var i = 0; i < a.length; i ++) { //遍历查询字符串数组
var pos = a[i].indexOf ("="); //找到等号的下标位置
if (pos == -1) continue; //如果没有等号,则忽略
var name = a[i].substring (0, pos); //获取等号前面的字符串
var value = a[i].substring (pos + 1); //获取等号后面的字符串
o[name] = unescape (value); //把名/值对传递给对象
}
var n, b;
//如果用户名等于“admin”,则记录该信息,否则设置为null
((o["user"]) && o["user"] == "admin") ? (n = o["user"]) : (n = null);
//如果密码存在,且等于“123456”,则设置变量b为true,否则为false
((o["pass"]) && o["pass"] == "123456") ? (b = true) : (b = false);
//调用客户端框架集中第1个框架中的回调函数,并把处理的信息传递给它
parent.frames[0].callback(b, n);
}
</script>
</head>
<body>
<h1>服务器端响应和处理页面</h1>
</body>
</html>
在实际开发中,服务器端文件一般为动态服务器类型的文件,并借助服务器端脚本来获取用户的信息,然后决定响应的内容,如,查询数据库、返回查询内容等。本示例以简化的形式演示异步通信的过程,因此没有采用服务器技术。
4) 预览框架集,在客户交互页面中输入用户的登录信息,当向服务器提交请求之后服务器首先接收从客户端传递过来的信息并进行处理,然后调用客户端的回调函数把处理后的信息响应回去。由于安全的原因,谷歌等浏览器不支持页面之间的连续跳转。在 IE 下,必须点击“允许阻止的内容”,方可在 IE 下正常运行。演示效果如图所示: