加controls属性才能启用默认播放控件;src属性存在兼容性问题,应优先使用source标签并声明type;autoplay需配合muted、loop、playsinline才有效;监听timeupdate前须等待loadedmetadata事件,拖动进度条应绑定input事件。

video标签加不加controls属性,直接决定你能不能省事
不加 controls 就等于放弃所有默认交互——没播放按钮、没进度条、没音量滑块,连右键菜单都可能消失。想“零起点”起步,第一件事就是确认是否真需要自定义 UI。如果只是嵌个课程视频或宣传片,controls 是最省力的起点;只有明确要换皮肤、加章节跳转、或做短视频全屏流,才值得去掉它再手动搭。
src 和 source 标签混用会翻车,优先用配双格式
写 <video src="xxx.mp4"></video> 看似简单,但 iOS Safari 会拒播 H.265 编码 MP4,Chrome 可能因服务端返回 text/plain MIME 类型而静默失败。实操必须用 <source></source> 显式声明类型:
-
<source src="video.mp4" type="video/mp4"></source>(H.264 + AAC 编码) -
<source src="video.webm" type="video/webm"></source>(VP9 + Opus,Chrome/Firefox 更稳)
服务器也得配对:.mp4 返回 video/mp4,.webm 返回 video/webm。本地开发别用 file:// 协议,起个 python3 -m http.server 才能触发正确 MIME 检查。
autoplay 要生效,muted、loop、playsinline 四个布尔属性一个都不能少
只写 autoplay 基本等于白写。Chrome 拦截有声自动播,iOS Safari 强制全屏,安卓 WebView 可能卡在黑帧。短视频页必须同时带:
-
autoplay(触发播放逻辑) -
muted(绕过音频策略) -
loop(避免播完中断) -
playsinline(iOS 内联播放开关,不能写成playsinline="true")
容器用 position: fixed 而不是 100vw/100vh,<video></video> 自身设 object-fit: cover 和 z-index: -1,内容层才不会被遮挡。
timeupdate 和 input 事件绑定错,进度条就不同步
监听 timeupdate 更新进度条时,先等 loadedmetadata 事件,否则 video.duration 是 NaN;拖动进度条必须用 input 事件(不是 change),否则移动端拖拽会断续跳帧:
video.addEventListener('loadedmetadata', () => {
seekBar.max = video.duration;
});
video.addEventListener('timeupdate', () => {
seekBar.value = video.currentTime;
});
seekBar.addEventListener('input', () => {
video.currentTime = seekBar.value;
});
注意:不要依赖 video.paused 判断状态,它在加载中或 autoplay 被拦截时不准。自己维护一个 let isPlaying = false 变量,从 play() 成功回调里更新,才可靠。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











