-
转载请声明出处:http://janpoem.cnblogs.com
Ajax在国内十分流行,到今天,基本上没有那个网站不使用Ajax了。利用现成的开源框架,或者自己稍微动手写一个Ajax的接口,都能很随意的实现Ajax。然后目前市面上所能见到的大多数的Ajax,实现到何种程度,是不是足够灵活,仍有待商榷。Ajax三十六"技",旨在讨论其设计模式和实现细节,如何才能更快速的利用现有网站的后台功能,实现更多更复杂的Ajax应用。
第一技 瞒天过海
网页的表单,一直是一个令人头疼的事情,尤其是当一个提交涉及到较多的SQL命令,在你post一个表单时,页面没有立即跳转到你设定的redirect到目标页面,而是看到浏览器底部的进度条在前进。有时候,基于服务器的综合性能考虑,会对数据库的响应进行一定的限制,加上国内网络环境的限制,这种延迟无法避免。 以下是一个基本的登录form:1 <form action="/sign_in" method="post">
2 <div>
3 <label for="login_name">用户名</label><input type="text" id="login_name" />
4 </div>
5 <div>
6 <label for="login_pwd">用户名</label><input type="password" id="login_pwd" />
7 </div>
8 <input type="submit" value="登录" />
9 </form>
接着是利用js对上述form的提交进行稍微的改造(js框架使用Prototype 1.6_rc1):
<
form
id
="sign_form"
action
="/sign_in"
method
="post"
>
< div >
< label for ="login_name" > 用户名 </ label >< input type ="text" id ="login_name" />
</ div >
< div >
< label for ="login_pwd" > 用户名 </ label >< input type ="password" id ="login_pwd" />
</ div >
< div id ="sign_error" ></ div >
< input type ="submit" value ="登录" />
</ form >
< script >
var isPost = false ; // 判断用户是否已经提交了登录
$( ' sign_form ' ).onsubmit = function () {
$( " sign_error " ).innerHTML = " 服务器正在验证数据,请稍候 " ;
if (isPost) // 避免用户重复提交
$( " sign_error " ).innerHTML = " 数据已提交,请等待服务器验证! " ;
else {
var params = { name: $( " login_name " ).value, pwd: $( " login_pwd " ).value };
$( " login_pwd " ).value = "" ; // 将用户密码保存在局部变量中,并清空密码输入框的值
isPost = ! isPost; // set isPost = true
new Ajax.Request( this .action, { // 请求的地址即为 form 的 action
method: ' post ' ,
parameters: params,
onComplete: function (request) {
isPost = ! isPost; // set isPost = false
var content = request.responseText;
if ( /* 当成功的状态 */ ) {
$( " sign_error " ).innerHTML = " 登录成功! " ;
setTimeout( function () { location.reload( true ); }, 100 );
}
else { // 失败的请求
var msg = content; // 捕获错误的提示信息,如"不存在该用户"等
$( " sign_error " ).innerHTML = msg; // 对页面输出错误信息
/* 以下添加错误状态的客户端前台控制 */
$( " login_name " ).focus();
$( " login_name " ).select();
}
}
});
}
return false ; // 取消该 form 的提交
}
</ script >
< div >
< label for ="login_name" > 用户名 </ label >< input type ="text" id ="login_name" />
</ div >
< div >
< label for ="login_pwd" > 用户名 </ label >< input type ="password" id ="login_pwd" />
</ div >
< div id ="sign_error" ></ div >
< input type ="submit" value ="登录" />
</ form >
< script >
var isPost = false ; // 判断用户是否已经提交了登录
$( ' sign_form ' ).onsubmit = function () {
$( " sign_error " ).innerHTML = " 服务器正在验证数据,请稍候 " ;
if (isPost) // 避免用户重复提交
$( " sign_error " ).innerHTML = " 数据已提交,请等待服务器验证! " ;
else {
var params = { name: $( " login_name " ).value, pwd: $( " login_pwd " ).value };
$( " login_pwd " ).value = "" ; // 将用户密码保存在局部变量中,并清空密码输入框的值
isPost = ! isPost; // set isPost = true
new Ajax.Request( this .action, { // 请求的地址即为 form 的 action
method: ' post ' ,
parameters: params,
onComplete: function (request) {
isPost = ! isPost; // set isPost = false
var content = request.responseText;
if ( /* 当成功的状态 */ ) {
$( " sign_error " ).innerHTML = " 登录成功! " ;
setTimeout( function () { location.reload( true ); }, 100 );
}
else { // 失败的请求
var msg = content; // 捕获错误的提示信息,如"不存在该用户"等
$( " sign_error " ).innerHTML = msg; // 对页面输出错误信息
/* 以下添加错误状态的客户端前台控制 */
$( " login_name " ).focus();
$( " login_name " ).select();
}
}
});
}
return false ; // 取消该 form 的提交
}
</ script >
首先,区别第一段代码,我们为form捆绑了id:sign_form,以及添加了一个错误提示层:sign_error。
其次,在js中:
- 显式的声明了一个变量isPost来限制用户重复post
- 通过对客户端的状态输出以及DOM控制,对用户行为进行引导,比:基于页面redirect的方式对用户操作进行提示,前者体验性更佳。网站的风险,往往来自前端的引导不足和流程繁琐,因为这些因素会让用户生出反感,而进行一些超出网站设计意图的操作,比如不断按“提交”,进行一些恶性的行为,比如故意漏填表单中的某个项,或者刻意提交非法字符,“以挑战网页制作人员的专业程度和耐性”。
- 对一个form事件实现初步的多态控制,这个世界是纷繁复杂的,基于服务器端的多态控制会让人抓狂的,倒不如通过前台实现来的快捷。
- 最关键的是,通过信息的及时反馈,隐匿了post操作的等待与延迟。实际上,我们需要的仅仅是通过登录,让客户端持有一个session,然后让页面reload,或者redirect到其他地方去。
以上的示例,可以进行一个简单的封装:
<
script
>
var isPost = false ;
/* * * * * * * * * * * * * * * * * * *
* An Ajax post method sample.
* Created by Janpoem 2008.3.1
* * * * * * * * * * * * * * * * * * */
ajaxPost = function (params, callback) {
var form = this ;
if (callback && callback.before) callback.before.call();
if (isPost) {
if (callback && callback.onPosted) callback.onPosted.call();
}
else {
isPost = ! isPost;
new Ajax.Request(form.action, {
method: form.method,
parameters: params,
onComplete: function (request) {
isPost = ! isPost;
var content = request.responseText;
if (callback && callback.roundback) callback.roundback.call(form, content);
}
})
if (callback && callback.after) callback.after.call();
}
return false ;
}
</ script >
< form id ="sign_form" action ="/sign_in" method ="post" >
< div >
< label for ="login_name" > 用户名 </ label >< input type ="text" id ="login_name" />
</ div >
< div >
< label for ="login_pwd" > 用户名 </ label >< input type ="password" id ="login_pwd" />
</ div >
< div id ="sign_error" ></ div >
< input type ="submit" value ="登录" />
</ form >
< script >
$( ' sign_form ' ).onsubmit = function () {
ajaxPost.call( this , { name: $( " login_name " ).value, pwd: $( " login_pwd " ).value }, {
before: function () { $( " sign_error " ).innerHTML = " 服务器正在验证数据,请稍候 " ; },
onPosted: function () { $( " sign_error " ).innerHTML = " 数据已发送,请等到服务验证! " ; },
roundback: function (msg) {
if ( /* 当成功的状态 */ ) {
$( " sign_error " ).innerHTML = " 登录成功! " ;
setTimeout( function () { location.reload( true ); }, 100 );
}
else {
$( " sign_error " ).innerHTML = msg;
$( " login_name " ).focus();
$( " login_name " ).select();
}
},
after: function () { $( " login_pwd " ).value = "" ; }
})
};
</ script >
var isPost = false ;
/* * * * * * * * * * * * * * * * * * *
* An Ajax post method sample.
* Created by Janpoem 2008.3.1
* * * * * * * * * * * * * * * * * * */
ajaxPost = function (params, callback) {
var form = this ;
if (callback && callback.before) callback.before.call();
if (isPost) {
if (callback && callback.onPosted) callback.onPosted.call();
}
else {
isPost = ! isPost;
new Ajax.Request(form.action, {
method: form.method,
parameters: params,
onComplete: function (request) {
isPost = ! isPost;
var content = request.responseText;
if (callback && callback.roundback) callback.roundback.call(form, content);
}
})
if (callback && callback.after) callback.after.call();
}
return false ;
}
</ script >
< form id ="sign_form" action ="/sign_in" method ="post" >
< div >
< label for ="login_name" > 用户名 </ label >< input type ="text" id ="login_name" />
</ div >
< div >
< label for ="login_pwd" > 用户名 </ label >< input type ="password" id ="login_pwd" />
</ div >
< div id ="sign_error" ></ div >
< input type ="submit" value ="登录" />
</ form >
< script >
$( ' sign_form ' ).onsubmit = function () {
ajaxPost.call( this , { name: $( " login_name " ).value, pwd: $( " login_pwd " ).value }, {
before: function () { $( " sign_error " ).innerHTML = " 服务器正在验证数据,请稍候 " ; },
onPosted: function () { $( " sign_error " ).innerHTML = " 数据已发送,请等到服务验证! " ; },
roundback: function (msg) {
if ( /* 当成功的状态 */ ) {
$( " sign_error " ).innerHTML = " 登录成功! " ;
setTimeout( function () { location.reload( true ); }, 100 );
}
else {
$( " sign_error " ).innerHTML = msg;
$( " login_name " ).focus();
$( " login_name " ).select();
}
},
after: function () { $( " login_pwd " ).value = "" ; }
})
};
</ script >
怎么样,还没晕头吧?好吧,今天的讲解到此为止啦!
瞒天过海者,原计释:备周则意怠,常见则不疑。阴在阳之内,不在阳之对。太阳,太阴。这就是今天的全部精髓了。