我要实现的效果是:当管理员单击下拉列表对用户的审核状态进行更改之后,将要修改的用户id和目前审核状态发送至后台,在后台处理完之后将信息反馈给前端,并进行一些提示,效果如图:
将提示信息显示在被处理用户信息同一行的一个单元格里面。
简单的思路:用jquery.post也好xmlhttprequest.open也好,当管理员对某一行的审核状态进行修改的时候,收集用户编号和修改后的审核状态,发送给后台,后台将处理的结果反馈回来,当前端得到后台的反馈之后,执行事先定义的回调函数,进行相应的提示操作:
jQuery.post( url, {id:2,state:good}, function(){ //more cord…… } );
问题的关键来了,从服务器反馈的信息可以知道要显示操作成功还是操作失败,但是,你要在表格里面显示提示信息,至少要知道提示信息要显示在第几行吧,然而后台并不是万能的,这么“前端”的问题,就不要为难后台了。
也许你会说,那就定义一个js的全局变量,记录管理员操作的记录是哪一行的,到时候后台反馈了就能直接定位显示了,好吧,这个暂时是解决了,假如,这个管理员的手很快,而后台的反应很慢,管理员处理了五六个,后台才返回其中一个的处理信息呢?也许你又会说,定一个数组吧,存放被处理的行号,然后要求后台在返回处理结果的同时也返回id,然后balabalabala捣鼓一下就能显示了⊙﹏⊙b,咱能不能有点追求呀。
好了引出我要说的主题js闭包,上面的问题,在我看来比较顺眼的处理方式是:在每一个给jquery.post或xmlhttprequest.open注册回调函数的时候,将对应要显示提示信息的label或是span也一并传进去,执行回调的时候就很方便啦,于是乎有了以下面的初步成果:
function callback(value){ alert(value); } jQuery.post( url, {id:2,state:good}, callback("helloworld"); );
但是发现只要jQuery.post方法一执行,就马上弹出helloworld的对话框,照我的理解,诸如函数名后面加个括号:functionName(),就等于是函数调用,执行到那里就直接调用了(个人理解,仅供参考),好了虽然这个方法不行,但大概明确了目标,要将一个值传给一个函数,而在传的同时这个函数得等到我们需要的时候才能执行,使用闭包就能实现这个效果了:
function parent_fun(value){ var name=value; function child(){ alert(name); } return child; } function test(){ var fun=parent_fun("helloword"); fun(); }
parent_child函数定义了一个局部变量name和一个函数child,然后将child函数返回出去,在执行了parent_child("helloword")之后就会得到返回的child函数,同时child函数的alert(name);这句中的name还是指向父函数parent_child的局部变量name,而在child函数被返回的时候,child并没有被执行,这个过程下来之后就大概达到了我们之前的目的了,child函数中使用的参数是我们预先传给parent_child的,而且child函数的执行也是可以由我们控制的。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
<table > //方便起见只有一行 <tr> <th>编号</th> <th>用户名</th> <th>审核状态</th> </tr> <tr> <td>1</td> <td>jim</td> <td> <select onchange="change(this)"> <option value=0>审核通过</option> <option value=1>审核不通过</option> </select> <span></span> //这里是放置提示信息的地方!!!!! </td> </tr> </table>
然后是js代码:
//当select的onchange事件触发之后执行的函数 function change(mySelect){ var myTr=$(mySelect).parent().parent();//获取到select所在的行tr元素 var mySapn=myTr.find("span")[0]; //查找到所在行的span元素 var id=myTr.find("td")[0].innerHTML; //获取用户编号 var shenhe=mySelect.value; //获取审核状态 var callback=callback_parent(mySelect); //将要显示提示信息的span传进去,得到回调函数 jQuery.post( url, //请求的url {ID:id,ShenHe:shenhe}, //请求的参数 function(data){ //回调函数 callback(data); } ); } //获取jQuery.post中后台数据回传后执行的回调函数 function callback_parent(arg){ var mySpan=arg; function callback(msg){ $(mySpan).attr("innerHTML",msg);//根据传入的参数,更改对应span的显示信息 } return callback; //将函数返回 }
var o={ name:"雷锋", info:"助人为乐" }
那么上面也能用下面的方法来实现:
//当select的onchange事件触发之后执行的函数
function change(mySelect){
var myTr=$(mySelect).parent().parent();//获取到select所在的行tr元素
var mySapn=myTr.find("span")[0]; //查找到所在行的span元素
var id=myTr.find("td")[0].innerHTML; //获取用户编号
var shenhe=mySelect.value; //获取审核状态
var callbackObject={ //这里是不一样的地方 span_:mySpan,
callback:function(msg){
$(this.span_).attr("innerHTML",msg); //这里使用this.span_调用
}
};
jQuery.post(
url, //请求的url
{ID:id,ShenHe:shenhe}, //请求的参数
function(data){ //回调函数
callbackObject(data); //这里没有什么变化
}
);
}
但是这样做的缺点也是明显的,就是不能重用,如果你有很多地方都要使用这个回调函数,那么每个地方都要重新写过了,如果只是临时使用,这个也不失为一个好方法