JQuery滚动事件无法检测元素更新的data-id值问题
反向无限滚动中data-id更新后无法获取新值的问题解决
问题描述
开发聊天应用时实现反向无限滚动:初始加载20条消息(id范围81-100),将最小id(81)存入聊天容器的data-id属性;用户滚动到顶部时,通过AJAX发送当前最小id给后端,查询更早的20条数据(id < 当前最小id),随后把新数据前置到列表,并更新data-id为新的最小id(比如61)。
但实际运行中,首次滚动能正确获取id=81,更新data-id后,再次触发滚动事件时,始终只能拿到旧值81,无法读取更新后的61。
现有代码
JavaScript
var chatBox = $(".retrive-chat"); $('.chat-box').scroll(function (event) { var st = $(this).scrollTop(); var lastid = $(this).find(".retrive-chat").data('id'); console.log(lastid); // 始终返回旧值 // 滚动到顶部时前置旧消息 if(st <= 10){ $.ajax({ url: 'processes/chat.php', type: 'POST', data: 'type=loadmore&to='+to+'&lastid='+lastid, dataType: 'JSON', success: function(data){ chatBox.attr('data-id', data.mid); // 获取新数据后更新值 chatBox.prepend(data.html); } }); } });
HTML
<div class="retrive-chat" data-id="81"></div>
问题原因
jQuery的data()方法会缓存DOM元素data属性的初始值,后续用attr()修改DOM上的data-id属性时,不会同步更新这个缓存,所以每次调用data('id')拿到的都是第一次加载时的旧值。
解决方案
两种简单解决方式任选其一即可:
方式1:用attr()代替data()读取值
直接从DOM属性读取最新值,不依赖jQuery的缓存:
// 修改获取lastid的代码 var lastid = $(this).find(".retrive-chat").attr('data-id');
更新data-id的代码保持chatBox.attr('data-id', data.mid);不变,这样每次读取的都是DOM上的最新属性值。
方式2:用data()同步更新缓存
如果想继续用data()方法读取,更新时也要用data()设置,确保缓存与DOM属性同步:
// 修改success回调里的更新代码 chatBox.data('id', data.mid);
这样后续调用data('id')就能拿到最新的缓存值。
额外优化:防止重复请求
滚动事件会频繁触发,建议添加加载状态锁,避免同一时间多次发送AJAX请求:
var chatBox = $(".retrive-chat"); var isLoading = false; // 加载状态锁 $('.chat-box').scroll(function (event) { var st = $(this).scrollTop(); var lastid = $(this).find(".retrive-chat").attr('data-id'); console.log(lastid); // 仅当滚动到顶部且未在加载时发送请求 if(st <= 10 && !isLoading){ isLoading = true; $.ajax({ url: 'processes/chat.php', type: 'POST', data: 'type=loadmore&to='+to+'&lastid='+lastid, dataType: 'JSON', success: function(data){ chatBox.attr('data-id', data.mid); chatBox.prepend(data.html); }, complete: function(){ isLoading = false; // 请求完成后解锁 } }); } });
内容的提问来源于stack exchange,提问作者Super Coder
相关产品推荐
相关产品推荐

