ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

react-use 全屏 Hook 实战指南:useFullscreen 源码剖析与 iOS 视频全屏降级方案

react-use 全屏 Hook 实战指南:useFullscreen 源码剖析与 iOS 视频全屏降级方案 react-use 全屏 Hook 实战指南useFullscreen 源码剖析与 iOS 视频全屏降级方案【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use导读useFullscreen是 react-use 提供的 UI 类 Hook用于将任意 DOM 元素如div、video一键切换为浏览器全屏模式并同步返回当前是否处于全屏状态的布尔值。它内部基于screenfull库封装了全屏 API 的跨浏览器差异同时为 iOS Safari 等不支持标准 Fullscreen API 的环境提供了基于webkitEnterFullscreen的视频全屏降级方案。读完本文你将掌握useFullscreen的完整用法、参数语义、iOS 降级原理及其底层实现细节并能直接在自己的 React 项目中落地。一、Hook 概览功能定位与调用签名useFullscreen的官方文档定位非常明确Display an element full-screen, optional fallback for fullscreen video on iOS——让指定元素全屏显示并为 iOS 上的视频全屏提供可选的降级方案。它被归类在 README.md 的 UI界面交互类别中与之并列的是useFullscreen之外的useHover、useMouse等 UI 相关 Hook。从 源码 可以看到其完整的 TypeScript 签名const useFullscreen ( ref: RefObjectElement, enabled: boolean, options: FullScreenOptions {} ): boolean即useFullscreen(ref, show, { onClose })三个参数的含义分别是参数类型说明refRefObjectElement指向要全屏显示的目标 DOM 元素的 refenabledboolean是否开启全屏的受控开关为true时触发全屏为false时退出全屏optionsFullScreenOptions可选配置默认值为{}返回值是一个boolean表示当前是否处于全屏状态可直接渲染到界面或用于条件样式。options 配置项详解FullScreenOptions接口定义如下见 src/useFullscreen.tsexport interface FullScreenOptions { video?: RefObject HTMLVideoElement { webkitEnterFullscreen?: () void; webkitExitFullscreen?: () void } ; onClose?: (error?: Error) void; }videoHTMLVideoElement的 ref并附加了可选的webkitEnterFullscreen/webkitExitFullscreen方法类型。仅在标准全屏 API 不可用如 iOS时发挥作用用于走视频的私有全屏接口。onClose退出全屏时的回调可选参数为error。当全屏请求抛出异常、用户按 Esc 退出全屏、或程序化退出全屏时都会被调用。默认值为noop空函数定义于 src/misc/util.ts。二、标准用法受控开关 状态回读官方文档给出的示例完整展示了最典型的用法——将useFullscreen与useToggle组合用一个受控布尔值驱动全屏并在退出全屏时把开关复位import {useFullscreen, useToggle} from react-use; const Demo () { const ref useRef(null) const [show, toggle] useToggle(false); const isFullscreen useFullscreen(ref, show, {onClose: () toggle(false)}); return ( div ref{ref} style{{backgroundColor: white}} div{isFullscreen ? Fullscreen : Not fullscreen}/div button onClick{() toggle()}Toggle/button video srchttp://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4 autoPlay / /div ); };这个示例的关键设计点ref 绑定目标div通过ref{ref}与 Hook 的第一个参数建立联系useFullscreen会对ref.current发起全屏请求。受控驱动show来自useToggle(false)作为第二个参数enabled。toggle()切换全屏的开启与关闭。退出复位onClose: () toggle(false)保证无论用户通过什么方式退出全屏Esc 键、浏览器 UI 或程序调用开关状态都能同步回false避免界面显示全屏、实际已退出的状态错位。状态回读Hook 返回的isFullscreen用于条件渲染文案也可以用于切换背景色等样式。更完整的实战变体仓库中的 Storybook 示例 stories/useFullscreen.story.tsx 展示了更完整的实战形态——同时管理目标元素与视频元素两个 ref并额外传入video配置以启用 iOS 降级const Demo () { const [show, toggle] useToggle(false); const ref React.useRef(null); const videoRef React.useRef(null); const isFullScreen useFullscreen(ref, show, { onClose: () toggle(false), video: videoRef, }); return ( div div ref{ref} style{{ backgroundColor: isFullScreen ? black : grey, ... }} video ref{videoRef} src... autoPlay{true} / {isFullScreen controls} /div {!isFullScreen controls} /div ); };注意两点实战细节传入video配置时务必给video元素本身也挂上对应的videoRef否则降级分支拿不到视频元素示例中用isFullScreen同时驱动背景色和按钮组的显隐这正是返回值即实时全屏状态的典型应用。三、底层原理从 enabled 到全屏生效的完整调用链useFullscreen的全部逻辑都封装在useIsomorphicLayoutEffect中见 src/useFullscreen.ts。useIsomorphicLayoutEffect 在浏览器环境使用useLayoutEffect在绘制前同步执行避免全屏状态闪烁在非浏览器环境回退为useEffect保证 SSR 安全。3.1 全屏请求分支enabled 为 true 时useIsomorphicLayoutEffect(() { if (!enabled) { return; } if (!ref.current) { return; } // ... }, [enabled, video, ref]);当enabled为false时直接跳过不做任何操作当ref.current尚不存在元素未挂载时同样跳过避免空引用错误。随后根据screenfull.isEnabled分流screenfull是 react-use 在 package.json 中声明的^5.1.0依赖分支 A标准 Fullscreen API 可用screenfull.isEnabled truetry { screenfull.request(ref.current); setIsFullscreen(true); } catch (error) { onClose(error); setIsFullscreen(false); } screenfull.on(change, onChange);调用screenfull.request(ref.current)发起全屏请求请求成功后立即将内部状态置为true若抛出异常例如浏览器拒绝、权限限制调用onClose(error)并把状态复位为false同时注册change事件监听用于跟踪全屏状态的变化。分支 B标准 API 不可用但有 iOS 视频降级能力video.current.webkitEnterFullscreen存在video.current.webkitEnterFullscreen(); on(video.current, webkitendfullscreen, onWebkitEndFullscreen); setIsFullscreen(true);iOS Safari 不支持element.requestFullscreen()此时走webkitEnterFullscreen()私有接口让视频全屏监听webkitendfullscreen事件在视频退出全屏时调用onClose()。分支 C两者都不可用onClose(); setIsFullscreen(false);直接回调onClose()并保持非全屏状态优雅降级不抛错。3.2 change 事件与退出全屏的检测const onChange () { if (screenfull.isEnabled) { const isScreenfullFullscreen screenfull.isFullscreen; setIsFullscreen(isScreenfullFullscreen); if (!isScreenfullFullscreen) { onClose(); } } };当用户按 Esc 或通过浏览器原生 UI 退出全屏时screenfull触发change事件Hook 会读取screenfull.isFullscreen的最新值并同步到内部状态若检测到已退出全屏isScreenfullFullscreen false调用onClose()让外部开关如useToggle复位。这就是文档示例中按 Esc 退出后 Toggle 按钮状态自动恢复的实现机制。3.3 清理函数组件卸载或 enabled 变化时退出全屏return () { setIsFullscreen(false); if (screenfull.isEnabled) { try { screenfull.off(change, onChange); screenfull.exit(); } catch {} } else if (video video.current video.current.webkitExitFullscreen) { off(video.current, webkitendfullscreen, onWebkitEndFullscreen); video.current.webkitExitFullscreen(); } };当enabled变为false、video或ref引用变化、或组件卸载时清理函数执行将全屏状态复位为false标准分支移除change监听并调用screenfull.exit()主动退出全屏异常被catch {}静默吞掉防止退出时报错影响组件iOS 分支移除webkitendfullscreen监听并调用webkitExitFullscreen()退出视频全屏。依赖数组[enabled, video, ref]意味着只要开关状态或 ref 引用变化Effect 就会先清理旧的全屏会话再按最新参数重新建立。四、内部状态与返回值的一致性isFullscreen的初始值直接取自enableduseState(enabled)见 src/useFullscreen.ts此后由三处驱动更新全屏请求成功后setIsFullscreen(true)change事件中按screenfull.isFullscreen同步清理函数中统一复位为false。因此在正常流程下返回值始终与浏览器的真实全屏状态保持一致即使全屏请求失败或用户主动退出返回值也会被及时纠正——这正是该 Hook 适合直接驱动 UI 条件渲染的原因。五、使用注意事项与适用边界结合源码逻辑使用useFullscreen时有几点值得注意全屏请求必须在用户手势中触发浏览器安全策略要求全屏请求由用户交互点击等发起。文档示例通过按钮点击触发toggle()间接驱动enabled变为true正是为了满足这一约束直接在useEffect中无条件置true可能被浏览器拒绝此时会走onClose(error)分支。enabled是受控开关而非一次性指令false → true触发全屏true → false触发退出经由清理函数。切勿把它当作只触发一次的副作用标志。iOS 降级只针对视频video配置项仅在使用webkitEnterFullscreen的 iOS 环境下生效普通div元素在 iOS Safari 上无法通过本 Hook 全屏screenfull.isEnabled为false且无视频降级能力时会走分支 C 优雅降级。onClose是状态同步的关键强烈建议像文档示例那样在onClose中复位外部开关否则会出现Hook 已退出全屏、外部开关仍为 true的不一致状态。SSR 安全由于底层使用useIsomorphicLayoutEffect在服务端渲染环境下不会执行全屏相关副作用。六、总结useFullscreen以极简的(ref, enabled, options)接口封装了跨浏览器的全屏能力标准环境走screenfull的 Fullscreen API 并实时同步状态iOS 环境降级为视频的webkitEnterFullscreen全程通过onClose回调保证外部状态与真实全屏状态一致。配合 src/useFullscreen.ts 的实现与 stories/useFullscreen.story.tsx 的完整示例开发者可以直接照搬接入自己的 React 项目实现播放器全屏、图片预览、报表大屏等常见交互。【免费下载链接】react-useReact Hooks — 项目地址: https://gitcode.com/gh_mirrors/re/react-use创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表