点击列表项触发视频切换的核心是监听点击事件,获取视频地址赋值给<video>的src,再调用load()和play();必须同步执行play()、添加preload="metadata"、用onloadeddata时机高亮当前项,并捕获play() Promise异常。
核心是监听列表元素的点击事件,拿到对应视频地址后赋值给 <video> 标签的 src 属性,再调用 load() 和 play()。不调用 load() 容易出现“切换后黑屏但有声音”或“仍播上一个视频”的问题。
<button> 或带 data-src 属性的 <li>,避免用纯文本 <div> 导致语义不清和键盘不可访问videoEl.pause(),否则多个视频可能同时加载音频流type 属性或清空 <source> 后重新 append靠 CSS 类控制视觉反馈,但关键在于「类名添加时机」:必须等 load() 成功后再加,否则可能刚点完就高亮,结果视频因网络失败没切过去。可用 videoEl.onloadeddata 作为可靠钩子。
active 类,再给当前项添加——别只加不删,否则高亮会累积videoEl.currentTime === 0 判断是否为新视频,有些浏览器会缓存首帧,导致误判本质是视频资源未预加载。浏览器默认对非自动播放的 <video> 不预加载元数据,所以首次点击要等整个视频头下载完才能播放。解决方向是提前 fetch 元数据,但得权衡带宽和首屏性能。
<video> 加 preload="metadata",比 auto 更轻量,能加快尺寸/时长读取fetch(videoUrl, { method: 'HEAD' }) 触发 DNS 预解析和连接复用onclick 里直接写 video.src = url; video.play(),缺少错误捕获;应包裹 try/catch 并监听 onerror 显示 fallback 提示iOS Safari 和部分安卓 WebView 要求视频播放必须由用户手势直接触发,且不能在异步回调(如 setTimeout、Promise.then)里调用 play()。这是最常被忽略的硬性限制。
立即学习“前端免费学习笔记(深入)”;
play() 在原生点击事件回调的同步执行路径内,比如 button.addEventListener('click', () => { video.src = x; video.load(); video.play(); })
play() 挪到 onloadeddata 里——这个事件是异步的,iOS 会拒绝播放playsinline 和 webkit-playsinline 属性,否则 iOS 会全屏弹出播放器video.play() 的 Promise 返回值经常被忽略——它可能 reject,而你不会看到任何报错,除非显式 catch。这点在调试无响应时特别容易卡住。