onended 是 DOM 事件处理器而非 HTML 属性,内联写法不可靠;应使用 addEventListener 绑定 ended 事件,并结合 dataset、CSP 兼容性、用户交互状态及资源加载时机等综合处理自动连播逻辑。

onended 是事件监听器,不是属性
很多人以为 onended 是 <video> 的 HTML 属性,直接写成 <video onended="location.href='next.html'"> —— 这样写语法上合法,但实际不会按预期跳转。因为 onended 是 DOM 事件处理器,它的值必须是可执行的 JavaScript 表达式或函数调用,且在内联写法中作用域受限(比如无法访问外部变量),还容易被 CSP 策略拦截。
推荐用 addEventListener 绑定 onended
更可靠、更可控的方式是在 JS 中用 addEventListener 监听 ended 事件:
const video = document.querySelector('video');
video.addEventListener('ended', () => {
// 假设下一集 URL 存在 data-next 属性里
const nextUrl = video.dataset.next;
if (nextUrl) {
location.href = nextUrl;
}
});
-
dataset.next比硬编码 URL 更灵活,支持动态生成(比如从 JSON 列表取第 n+1 项) - 避免内联脚本,兼容 CSP strict 模式
- 可以加判断逻辑:比如用户是否已登录、是否开启自动连播、是否在试看片段等
- 如果页面有多个
<video>,记得为每个实例单独绑定,或用事件委托 +event.target区分
注意播放结束 ≠ 视频加载完成
遇到“跳转了但新页面视频黑屏/卡住”,大概率是因为下一集资源还没加载好,或者当前页未清理前一个视频的状态。几个关键点:
-
ended事件只表示当前<video>播放自然结束(到末尾),不保证网络就绪或 DOM 已更新 - 如果用单页应用(如 Vue/React),直接
location.href会整页刷新;想无刷新切换,得用路由跳转 + 手动重置<video>的src和load() - 某些浏览器(尤其是移动端 Safari)对自动跳转有拦截:如果跳转逻辑不在用户手势触发的上下文中,
location.href可能静默失败 - 建议加个简单 fallback:跳转前检查
nextUrl是否为有效 URL,否则提示“已是最后一集”
自动连播时别忽略用户操作意图
用户点暂停、拖进度条、切后台再回来,都可能影响 ended 的触发时机。真实场景中需要:
立即学习“前端免费学习笔记(深入)”;
- 监听
pause和seeking事件,临时禁用自动跳转逻辑(比如设个isUserInteracted = true) - 如果视频被
play()拒绝(比如无用户手势),ended依然会触发,但后续跳转可能失败 —— 要捕获Promisereject 或检查video.readyState - 不要在
ended回调里直接调video.play()(下一集还没 load),而是先video.src = nextUrl,再video.load(),等loadeddata后再play()
连播逻辑越靠近真实播放链路,越容易漏掉边界情况。比如用户刚点完“下一集”按钮,又触发了上一集的 ended,就得靠防抖或状态锁来避免重复跳转。



















