为Ajax动态追加的视频元素初始化jQuery与JavaScript的问题
Ajax追加视频后的事件绑定与单次触发解决方案
问题背景
滚动触发Ajax加载视频元素,页面初始加载的视频可正常触发播放/静音控制,但新追加的视频无法响应事件;同时点击/触摸事件要么仅触发一次,要么每次点击都重复触发,需要实现每次Ajax请求完成后,事件监听器可单次触发播放新视频。
问题分析
- 事件绑定失效:原视频的
play/pause/ended事件直接绑定在初始DOM元素上,新追加的视频元素未被绑定事件,需要用事件委托处理动态生成的元素。 - 单次触发逻辑冲突:原代码
{once: true}会让事件仅执行一次,但Ajax加载新视频后无法重新触发;移除该属性则每次点击都会重复执行播放函数,需要手动控制事件的绑定与移除。
解决方案
1. 修复视频静音控制的事件委托
将原有的视频事件绑定改为委托到父容器(main2),确保动态追加的视频也能触发事件,同时只操作当前触发事件的视频(避免影响全局所有视频):
// 替换原第2段代码 $('main2').on('play', 'video', function() { $(this).prop('muted', false); }); $('main2').on('pause', 'video', function() { $(this).prop('muted', true); }); $('main2').on('ended', 'video', function() { $(this).prop('muted', true); });
2. 实现Ajax加载后单次触发的点击/触摸事件
重构播放函数与事件绑定逻辑,每次Ajax加载完成后重新绑定单次触发的事件,触发后自动移除监听器:
第一步:重构播放函数与事件绑定逻辑
// 保留原原型扩展,替换第3段代码的其余部分 Object.defineProperty(HTMLMediaElement.prototype, 'playing', { get: function() { return !!(this.currentTime > 0 && !this.paused && !this.ended && this.readyState > 2); } }); function playVideoOnLowPower() { try { const videoElements = document.querySelectorAll("video"); // 使用let声明循环变量,避免全局变量污染 for (let i = 0; i < videoElements.length; i++) { if (!videoElements[i].playing) { videoElements[i].play(); console.log('开始播放视频'); } else { console.log('视频已在播放'); } } // 触发后手动移除事件监听器,实现单次触发 document.body.removeEventListener("click", playVideoOnLowPower); document.body.removeEventListener("touchstart", playVideoOnLowPower); } catch (err) { console.log(err); } } // 封装单次事件绑定函数 function bindPlayEventOnce() { // 不使用{once: true},改为手动移除 document.body.addEventListener("click", playVideoOnLowPower); document.body.addEventListener("touchstart", playVideoOnLowPower); } // 页面初始加载时绑定第一次事件 bindPlayEventOnce();
第二步:修改Ajax回调,每次加载后重新绑定事件
// 修改原第1段代码的Ajax成功回调 var step = 1; var loading = false; $(window).scroll(function() { if ($(window).scrollTop() >= $(document).height() - $(window).height() - 1900) { if (loading === false) { loading = true; $.ajax({ url: 'HTTPS://ENTER URL HERE.COM' + step, success: function(data) { step++; $('main2').append(data); loading = false; // 每次加载新视频后,重新绑定单次触发的播放事件 bindPlayEventOnce(); }, dataType: 'html' }); } } });
逻辑说明
- 事件委托:通过父容器
main2监听子元素video的事件,动态追加的视频自动继承事件绑定。 - 单次触发控制:每次Ajax加载后调用
bindPlayEventOnce绑定事件,播放函数执行后手动移除监听器,确保每次仅触发一次,下次Ajax加载后重新绑定。 - 变量优化:循环变量
i改用let声明,避免全局变量污染导致的逻辑错误。
内容的提问来源于stack exchange,提问作者DCM CODING
相关产品推荐
相关产品推荐

