React前端DOM常见Hook封装示例下

Jacuqeline ·
更新时间:2024-11-13
· 1354 次阅读

目录

引言

useFullscreen

useHover

useDocumentVisibility

引言

本文是深入浅出 ahooks 源码系列文章的第十五篇,这个系列的目标主要有以下几点:

加深对 React hooks 的理解。

学习如何抽象自定义 hooks。构建属于自己的 React hooks 工具库。

培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择。

上文指路: React前端DOM常见Hook封装示例上

本篇接着针对关于 DOM 的各个 Hook 封装进行解读。

useFullscreen

管理 DOM 全屏的 Hook。

该 hook 主要是依赖 screenfull 这个 npm 包进行实现的。

选择它的原因,估计有两个:

它的兼容性好,兼容各个浏览器的全屏 API。

简单,包体积小。压缩后只要 1.1 k。

大概介绍几个它的 API。

.request(element, options?)。使一个元素全屏显示。默认元素是 <html>

.exit()。退出全屏。

.toggle(element, options?)。假如目前是全屏,则退出,否则进入全屏。

.on(event, function)。添加一个监听器,用于当浏览器切换到全屏或切换出全屏或出现错误时。event 支持 'change' 或者 'error'。另外两种写法:.onchange(function).onerror(function)

.isFullscreen。判断是否是全屏。

.isEnabled。判断当前环境是否支持全屏。

来看该 hook 的封装:

首先是 onChange 事件中,判断是否是全屏,从而触发进入全屏的函数或者退出全屏的函数。 当退出全屏的时候,卸载 change 事件。

const { onExit, onEnter } = options || {}; // 退出全屏触发 const onExitRef = useLatest(onExit); // 全屏触发 const onEnterRef = useLatest(onEnter); const [state, setState] = useState(false); const onChange = () => { if (screenfull.isEnabled) { const { isFullscreen } = screenfull; if (isFullscreen) { onEnterRef.current?.(); } else { screenfull.off('change', onChange); onExitRef.current?.(); } setState(isFullscreen); } };

手动进入全屏函数,支持传入 ref 设置需要全屏的元素。并通过 screenfull.request 进行设置,并监听 change 事件。

// 进入全屏 const enterFullscreen = () => { const el = getTargetElement(target); if (!el) { return; } if (screenfull.isEnabled) { try { screenfull.request(el); screenfull.on('change', onChange); } catch (error) { console.error(error); } } };

退出全屏方法,调用 screenfull.exit()

// 退出全屏 const exitFullscreen = () => { if (!state) { return; } if (screenfull.isEnabled) { screenfull.exit(); } };

最后通过 toggleFullscreen,根据当前状态,调用上面两个方法,达到切换全屏状态的效果。

useHover

监听 DOM 元素是否有鼠标悬停。

主要实现原理是监听 mouseenter 触发 onEnter 事件,切换状态为 true,监听 mouseleave 触发 onLeave 事件,切换状态为 false。代码简单,如下:

export default (target: BasicTarget, options?: Options): boolean => { const { onEnter, onLeave } = options || {}; const [state, { setTrue, setFalse }] = useBoolean(false); // 通过监听 mouseenter 判断有鼠标悬停 useEventListener( 'mouseenter', () => { onEnter?.(); setTrue(); }, { target, }, ); // mouseleave 没有鼠标悬停 useEventListener( 'mouseleave', () => { onLeave?.(); setFalse(); }, { target, }, ); return state; }; useDocumentVisibility

监听页面是否可见。

这个 hook 主要使用了 Document.visibilityState 这个 API。先简单看下这个 API:

Document.visibilityState (只读属性), 返回document的可见性, 即当前可见元素的上下文环境。由此可以知道当前文档 (即为页面) 是在背后, 或是不可见的隐藏的标签页,或者 (正在) 预渲染。可用的值如下:

'visible' : 此时页面内容至少是部分可见. 即此页面在前景标签页中,并且窗口没有最小化。

'hidden' : 此时页面对用户不可见。即文档处于背景标签页或者窗口处于最小化状态,或者操作系统正处于 '锁屏状态' 。

'prerender' : 页面此时正在渲染中,因此是不可见的。文档只能从此状态开始,永远不能从其他值变为此状态。

典型用法是防止当页面正在渲染时加载资源,或者当页面在背景中或窗口最小化时禁止某些活动。

最后看这个 hook 的实现就很简单了:

通过 document.visibilityState 判断是否可见。

通过 visibilitychange 事件,更新结果。

const getVisibility = () => { if (!isBrowser) { return 'visible'; } // Document.visibilityState (只读属性), 返回document的可见性, 即当前可见元素的上下文环境。 return document.visibilityState; }; function useDocumentVisibility(): VisibilityState { const [documentVisibility, setDocumentVisibility] = useState(() => getVisibility()); useEventListener( // 监听该事件 'visibilitychange', () => { setDocumentVisibility(getVisibility()); }, { target: () => document, }, ); return documentVisibility; }

以上就是React前端DOM常见Hook封装示例下的详细内容,更多关于React前端 DOM Hook 封装的资料请关注软件开发网其它相关文章!



示例 React dom

需要 登录 后方可回复, 如果你还没有账号请 注册新账号