js动态循环绑定事件的变量问题,动态循环添加元素并绑定事件出现重复的问题
在编写JS的时候我们经常会遇到要对一系列元素进行事件绑定,循环对元素的事件进行赋值,在这个过程中我们会遇到一个问题,那就每个元素事件运行的时候变量怎么都是相同的值。
这里涉及到变量的作用域的问题,可以用闭包来解决这个问题。
这里举个简单的列子来说明:
- 数据
- 数据
- 数据
- 数据
- 数据
我们来给这些li添加一个onclick事件,弹出li是第几条数据
var list = document.getElementById("ulDemo").getElementsByTagName("li");
for (var i = 0; i < list.length; i++) {
var li = list[i];
li.onclick= function () {
alert("第" + (i + 1) + "条" + this.innerHTML);
}
}
结果弹出的都是第6条数据,这里的onclick函数中的变量i指向的内存地址,经过循环之后i变成了5,所有的li的点击事件都在同一个作用域中,我们可以通过闭包把i的作用域独立出来。
var list = document.getElementById("ulDemo").getElementsByTagName("li");
for (var i = 0; i < list.length; i++) {
var li = list[i];
li.onclick= (function (index) {
return function () { alert("第" + (index + 1) + "条" + this.innerHTML) };
})(i);
}
其他写法
for (var i = 0; i < list.length; i++) {
var li = list[i];
var addClick = function (el, index) {
el.onclick= function () { alert("第" + (index + 1) + "条" + this.innerHTML) };
};
addClick(li, i);
}
或
for (var i = 0; i < list.length; i++) {
var li = list[i];
(function (el,index) {
el.onclick= function () { alert("第" + (index + 1) + "条" + this.innerHTML) };
})(li,i);
}
示例代码:
//初始化mescroll1
function initmescroll1(){
var mescroll1 = new MeScroll("mescroll1", {
up: {
auto: true, //是否在初始化时以上拉加载的方式自动加载第一页数据; 默认false
isBounce: false, //此处禁止ios回弹,解析(务必认真阅读,特别是最后一点): http://www.mescroll.com/qa.html#q10
callback: upCallback, //上拉回调,此处可简写; 相当于 callback: function (page) { upCallback(page); }
clearEmptyId: "dataList", //1.下拉刷新时会自动先清空此列表,再加入数据; 2.无任何数据时会在此列表自动提示空
page: {
num: 0, //当前页 默认0,回调之前会加1; 即callback(page)会从1开始
size: 10 //每页数据条数,默认10
},
toTop:{ //配置回到顶部按钮
src : "../images/mescroll-totop.png", //默认滚动到1000px显示,可配置offset修改
offset : 1000
}
}
});
/*上拉加载的回调 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数 */
function upCallback(page){
ajaxSyncRequest(getContextPath() + "getServiceRecord", {"phone": userPhone, "pageNo": page.num}, function(data){
if(data.success){
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
//mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
//方法一(推荐): 后台接口有返回列表的总页数 totalPage
mescroll1.endByPage(data.data.rows.length, data.data.totalPage); //必传参数(当前页的数据个数, 总页数)
//方法二(推荐): 后台接口有返回列表的总数据量 totalSize
//mescroll.endBySize(curPageData.length, totalSize); //必传参数(当前页的数据个数, 总数据量)
//方法三(推荐): 您有其他方式知道是否有下一页 hasNext
//mescroll.endSuccess(curPageData.length, hasNext); //必传参数(当前页的数据个数, 是否有下一页true/false)
//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
//mescroll1.endSuccess(curPageData.length);
//设置列表数据
if(data.data.totalPage == "1" && data.data.rows.length == 0){
$("#mescroll1 .app_empty").show();
}else{
$("#mescroll1 .app_empty").hide();
setListData(data.data.rows);
}
}else{
//联网失败的回调,隐藏下拉刷新的状态
mescroll1.endErr();
}
});
}
/*设置列表数据*/
function setListData(curPageData){
var listDom = document.getElementById("dataList");
for (var i = 0; i < curPageData.length; i++) {
var data = curPageData[i];
var str='<p class="app_dl_t">'+data.station_name+'-'+data.charge_id+'<span class="fr col_ob">'+data.order_status+'</span></p>';
str+='<p class="app_dl_i">';
str+='<label>充电电量:'+data.charged_capacity+'度'+'</label>';
str+='<label>开始时间:'+data.start_time+'</label>';
str+='<label>结束时间:'+data.end_time+'</label>';
str+='<i><font class="col_oo">'+data.money+'</font>元</i></p>';
str+='<p class="app_dl_b"><a href="javascript:void(0);" class="fr curr_bt">申请售后</a><a href="javascript:void(0);" class="fr curr_bt">服务评价</a></p>';
var liDom = document.createElement("li");
liDom.innerHTML = str;
addClickListener(liDom, data);
listDom.appendChild(liDom);
}
}
/*添加列表点击事件*/
function addClickListener(el, data){
$(el).on('click', function(){
alert(data.order_num);
});
}
}
完!!!
还没有评论,来说两句吧...