React前端DOM常見Hook封裝示例下
引言
本文是深入淺出 ahooks 源碼系列文章的第十五篇,這個系列的目標主要有以下幾點:
- 加深對 React hooks 的理解。
- 學習如何抽象自定義 hooks。構建屬于自己的 React hooks 工具庫。
- 培養(yǎng)閱讀學習源碼的習慣,工具庫是一個對源碼閱讀不錯的選擇。
上文指路: React前端DOM常見Hook封裝示例上
本篇接著針對關于 DOM 的各個 Hook 封裝進行解讀。
useFullscreen
管理 DOM 全屏的 Hook。
該 hook 主要是依賴 screenfull 這個 npm 包進行實現(xiàn)的。
選擇它的原因,估計有兩個:
- 它的兼容性好,兼容各個瀏覽器的全屏 API。
- 簡單,包體積小。壓縮后只要 1.1 k。
大概介紹幾個它的 API。
- .request(element, options?)。使一個元素全屏顯示。默認元素是
<html>
- .exit()。退出全屏。
- .toggle(element, options?)。假如目前是全屏,則退出,否則進入全屏。
- .on(event, function)。添加一個監(jiān)聽器,用于當瀏覽器切換到全屏或切換出全屏或出現(xiàn)錯誤時。event 支持 'change' 或者 'error'。另外兩種寫法:
.onchange(function)
和.onerror(function)
。 - .isFullscreen。判斷是否是全屏。
- .isEnabled。判斷當前環(huán)境是否支持全屏。
來看該 hook 的封裝:
首先是 onChange 事件中,判斷是否是全屏,從而觸發(fā)進入全屏的函數(shù)或者退出全屏的函數(shù)。 當退出全屏的時候,卸載 change
事件。
const { onExit, onEnter } = options || {}; // 退出全屏觸發(fā) const onExitRef = useLatest(onExit); // 全屏觸發(fā) 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); } };
手動進入全屏函數(shù),支持傳入 ref 設置需要全屏的元素。并通過 screenfull.request
進行設置,并監(jiān)聽 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,根據(jù)當前狀態(tài),調用上面兩個方法,達到切換全屏狀態(tài)的效果。
useHover
監(jiān)聽 DOM 元素是否有鼠標懸停。
主要實現(xiàn)原理是監(jiān)聽 mouseenter
觸發(fā) onEnter 事件,切換狀態(tài)為 true,監(jiān)聽 mouseleave
觸發(fā) onLeave 事件,切換狀態(tài)為 false。代碼簡單,如下:
export default (target: BasicTarget, options?: Options): boolean => { const { onEnter, onLeave } = options || {}; const [state, { setTrue, setFalse }] = useBoolean(false); // 通過監(jiān)聽 mouseenter 判斷有鼠標懸停 useEventListener( 'mouseenter', () => { onEnter?.(); setTrue(); }, { target, }, ); // mouseleave 沒有鼠標懸停 useEventListener( 'mouseleave', () => { onLeave?.(); setFalse(); }, { target, }, ); return state; };
useDocumentVisibility
監(jiān)聽頁面是否可見。
這個 hook 主要使用了 Document.visibilityState 這個 API。先簡單看下這個 API:
Document.visibilityState
(只讀屬性), 返回document的可見性, 即當前可見元素的上下文環(huán)境。由此可以知道當前文檔 (即為頁面) 是在背后, 或是不可見的隱藏的標簽頁,或者 (正在) 預渲染??捎玫闹等缦拢?/p>
- 'visible' : 此時頁面內容至少是部分可見. 即此頁面在前景標簽頁中,并且窗口沒有最小化。
- 'hidden' : 此時頁面對用戶不可見。即文檔處于背景標簽頁或者窗口處于最小化狀態(tài),或者操作系統(tǒng)正處于 '鎖屏狀態(tài)' 。
- 'prerender' : 頁面此時正在渲染中,因此是不可見的。文檔只能從此狀態(tài)開始,永遠不能從其他值變?yōu)榇藸顟B(tài)。
典型用法是防止當頁面正在渲染時加載資源,或者當頁面在背景中或窗口最小化時禁止某些活動。
最后看這個 hook 的實現(xiàn)就很簡單了:
- 通過 document.visibilityState 判斷是否可見。
- 通過 visibilitychange 事件,更新結果。
const getVisibility = () => { if (!isBrowser) { return 'visible'; } // Document.visibilityState (只讀屬性), 返回document的可見性, 即當前可見元素的上下文環(huán)境。 return document.visibilityState; }; function useDocumentVisibility(): VisibilityState { const [documentVisibility, setDocumentVisibility] = useState(() => getVisibility()); useEventListener( // 監(jiān)聽該事件 'visibilitychange', () => { setDocumentVisibility(getVisibility()); }, { target: () => document, }, ); return documentVisibility; }
以上就是React前端DOM常見Hook封裝示例下的詳細內容,更多關于React前端 DOM Hook 封裝的資料請關注腳本之家其它相關文章!
相關文章
教你快速搭建 React Native 開發(fā)環(huán)境
這篇文章主要介紹了搭建 React Native 開發(fā)環(huán)境的詳細過程,本文通過圖文指令給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08react-player實現(xiàn)視頻播放與自定義進度條效果
本篇文章通過完整的代碼給大家介紹了react-player實現(xiàn)視頻播放與自定義進度條效果,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧2022-01-01React?Native?中處理?Android?手機吞字的解決方案
這篇文章主要介紹了React?Native?中處理?Android?手機吞字的解決方案,作者在 React Native 0.67.4 環(huán)境下,編寫了一個小 demo 來復現(xiàn)這個問題,需要的朋友可以參考下2022-08-08