转载请声明出处: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>
 
接着是sign_in的后台,首先要找到该用户,其次,也许你需要一个log,记录下用户登录的状况,比如ip,客户端状况等等,最后,当不存在该用户,你还必须朝客户端返回一定的信息,提示用户接续操作。

接着是利用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>

首先,区别第一段代码,我们为form捆绑了id:sign_form,以及添加了一个错误提示层:sign_error。

其次,在js中:

  1. 显式的声明了一个变量isPost来限制用户重复post
  2. 通过对客户端的状态输出以及DOM控制,对用户行为进行引导,比:基于页面redirect的方式对用户操作进行提示,前者体验性更佳。网站的风险,往往来自前端的引导不足和流程繁琐,因为这些因素会让用户生出反感,而进行一些超出网站设计意图的操作,比如不断按“提交”,进行一些恶性的行为,比如故意漏填表单中的某个项,或者刻意提交非法字符,“以挑战网页制作人员的专业程度和耐性”。
  3. 对一个form事件实现初步的多态控制,这个世界是纷繁复杂的,基于服务器端的多态控制会让人抓狂的,倒不如通过前台实现来的快捷。
  4. 最关键的是,通过信息的及时反馈,隐匿了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>

怎么样,还没晕头吧?好吧,今天的讲解到此为止啦!

瞒天过海者,原计释:备周则意怠,常见则不疑。阴在阳之内,不在阳之对。太阳,太阴。这就是今天的全部精髓了。

posted on 2008-03-01 15:49  Janpoem  阅读(252)  评论(0编辑  收藏  举报