不能将所有控件塞进 video-player__controls 一个块里,因播放、音量、全屏三者交互逻辑、dom 结构、状态粒度完全不同;plyr 要求控件必须用 plyr__control 类名+data-plyr 属性双重识别;音量需拆为独立的 video-player__volume-toggle 和 video-player__volume-slider;全屏状态须由 data-fullscreen 属性驱动以同步 document 级异步状态。

为什么不能把所有控件塞进 video-player__controls 一个块里
控件不是视觉上“排成一排”就该归为同个 Block。播放、音量、全屏三者交互逻辑、DOM 结构、状态粒度完全不同:播放按钮是 <button></button>,音量是 <input type="range">,全屏还涉及 document 级状态切换。强行共用 video-player__controls 并在内部写 video-player__controls__play,会导致:
- JS 控制静音时得同时操作
video-player__controls__volume-toggle和video-player__controls__volume-slider,耦合严重 -
video-player__controls--muted这种修饰符加在哪?加在容器上,但音量滑块可能仍显示 80%,状态不一致 - 响应式断点要隐藏音量滑块却保留按钮,就得写一堆
.video-player__controls--mobile .video-player__controls__volume-slider { display: none },破坏职责分离
plyr__control 是必须遵守的硬性约定,不是可选项
如果你用的是 Plyr,它的 JS 完全依赖 class="plyr__control" + data-plyr 属性双重识别。手写 video-player__play-btn 或只加 data-plyr="play" 都会失效:
-
<button class="plyr__control" data-plyr="play"></button>→ 正常触发播放/暂停 -
<button class="my-play-btn" data-plyr="play"></button>→ 点击无反应,JS 根本不监听 -
<button class="plyr__control"></button>(缺data-plyr)→ 被识别为普通控件,不绑定播放逻辑
进度条例外:plyr__progress 不是控件,不能加 plyr__control;它只是展示容器,内部子元素是 plyr__progress__buffer 和 plyr__progress__played。
音量控件必须拆成两个独立 Block:video-player__volume-toggle 和 video-player__volume-slider
它们不是“同一个功能的两部分”,而是两个语义独立、生命周期不同的组件:
-
video-player__volume-toggle:纯按钮,负责切换player.muted,状态修饰符是video-player__volume-toggle--muted -
video-player__volume-slider:滑块,负责映射player.volume值,显隐由 toggle 状态驱动,修饰符是video-player__volume-slider--hidden - 两者 DOM 位置可以相邻,但 class 名绝不允许嵌套,比如禁止
video-player__volume__toggle
这样 JS 只需监听 mute 切换事件,然后分别操作两个 Block 的类名,互不干扰,也方便单独测试或禁用。
全屏按钮的状态必须由 data-fullscreen 属性驱动,而非 --active 类
全屏是浏览器级异步操作,element.requestFullscreen() 调用后,document.fullscreenElement 不会立刻更新。如果 JS 在调用后立即加 video-player__fullscreen-btn--active,大概率比 fullscreenchange 事件早,造成 UI 滞后或误判:
- 正确做法:JS 监听
fullscreenchange,动态在根容器(如或.video-player)写data-fullscreen="true"或data-fullscreen="disabled" - CSS 用属性选择器响应:
body:is([data-fullscreen="true"]) .video-player__fullscreen-btn - iOS Safari 不支持全屏 API 时,设
data-fullscreen="disabled",样式里写.video-player__fullscreen-btn:is([data-fullscreen="disabled"]) { opacity: 0.4; pointer-events: none; }
纯靠 class 切换,等于放弃对 document 级状态的真实同步——这是最容易被忽略、也最常出竞态 bug 的地方。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











