網站首頁 編程語言 正文
引言
本文是深入淺出 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; }
原文鏈接:https://juejin.cn/post/7113500743935459336
相關推薦
- 2023-06-17 Queue隊列中join()與task_done()的關系及說明_python
- 2022-08-03 如何一鍵理清大型Python項目依賴樹_python
- 2023-01-12 Kotlin注解實現Parcelable序列化流程詳解_Android
- 2022-11-06 Python?munch包?/Munch()?的用法詳解_python
- 2022-05-24 SQL?Server表空間碎片化回收的實現_MsSql
- 2022-11-03 python如何判斷文件存在方式_python
- 2022-09-12 超實用的Nginx常見配置合集分享_nginx
- 2023-07-08 vs編譯運行報錯:未聲明的標識符
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支