用emit实现视频全屏切换:子组件点击时触发toggle-fullscreen事件并传参,父组件统一处理方向设置、布局更新与状态同步,符合单向数据流,避免props双向混乱。

用 emit 实现视频播放器全屏状态切换,关键是让子组件(如全屏按钮或视频容器)把用户操作意图“喊出来”,父组件“听见后”统一执行窗口旋转、布局调整或状态更新。它不直接控制屏幕方向,而是触发上层逻辑,确保父子职责清晰、响应可控。
子组件:点击即 emit,只管“喊一声”
全屏按钮本身不需要知道怎么旋转窗口、要不要隐藏标题栏,它只需在被点击时,通过 defineEmits 触发一个语义明确的事件,比如 toggle-fullscreen,并可附带当前期望的状态(如 isFullscreen: true)。
- 使用
const emit = defineEmits(['toggle-fullscreen'])声明可发出的事件 - 绑定
@click="emit('toggle-fullscreen', { isFullscreen: !isFullscreen })" - 图标或文案根据本地
isFullscreen状态切换(仅用于视觉反馈,不驱动真实行为)
父组件:接收 emit,统筹全局动作
父组件监听子组件发出的 toggle-fullscreen 事件,集中处理所有相关逻辑——调用系统 API 设置窗口方向、更新 UI 布局、同步播放器尺寸、甚至上报埋点。
- 在模板中写:
<videoplayer></videoplayer> - 在
setup中定义handleFullscreenToggle({ isFullscreen }) - 内部调用鸿蒙
window.setPreferredOrientation()(横屏用landscape,退出用portrait) - 同时更新自身
isFullscreen状态,供其他子组件(如返回按钮、进度条)响应式调整显示
状态同步与边界处理
全屏不是孤立动作,需和播放器生命周期、系统限制联动。emit 只是起点,后续必须补全闭环。
- 监听系统窗口方向变更事件(如鸿蒙的
onOrientationChanged),反向emit给子组件同步最新状态,应对用户手动旋转设备 - 进入全屏前检查
AVPlayer是否已 prepared,避免白屏;退出时恢复原 video 元素宽高比或重置 XComponent surface - 若使用页面跳转方案(非窗口旋转),则
emit后由父组件router.push()导航,并传参携带播放位置等上下文
为什么不用 props 直接控制?
全屏是**用户主动发起的命令型操作**,不是被动渲染的状态。用 props 下传 isFullscreen 容易导致“父控子、子又想改父”的双向绑定混乱。而 emit 明确表达了“我点了,请你决定怎么做”,符合 Vue 的单向数据流设计哲学,也便于后期扩展(例如加权限校验、动画过渡钩子)。










