现在我将问题的“上下文”详细说一下:
我要实现一个页面,让管理员对用户的权限进行管理,页面如下:
我要实现的效果是:当管理员单击下拉列表对用户的审核状态进行更改之后,将要修改的用户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的html代码:
<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; //将函数返回
}
还有一种方式可以实现上面的效果,试想,开辟一个地方,可以容纳一些属性,和方法,然后需要的时候可以调用这些方法同时使用那些属性,这些特征很像对象,在js中也能自己定义对象,比如:
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); //这里没有什么变化
}
);
}
但是这样做的缺点也是明显的,就是不能重用,如果你有很多地方都要使用这个回调函数,那么每个地方都要重新写过了,如果只是临时使用,这个也不失为一个好方法
来源:oschina
链接:https://my.oschina.net/u/189876/blog/40405