持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
今天开始一起学习分享 ahooks 的源码
ahooks是阿里巴巴出品的一套高质量可靠的 React Hooks 库
今天分享 第12个 hooks-useFullscreen
useFullscreen
首先看下 useFullscreen 的作用是什么
useFullscreen 的作用是管理 DOM 全屏的 Hook。
接下来 看下 API
API
const [ isFullscreen, { enterFullscreen, exitFullscreen, toggleFullscreen, isEnabled, }] = useFullScreen(
target,
options?: Options
);
Params
参数一共2个
第1个参数是要设置的目标元素,可以传入dom节点,也可以使用ref指定dom节点
第2个参数是配置的参数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| target | DOM 节点或者 ref | Element | () => Element | MutableRefObject<Element> | - |
| options | 设置 | Options | - |
Options
配置的参数一共2个
第1个是 onExit,表示退出全屏触发的函数
第2个是 onEnter,表示全屏触发的函数
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| onExit | 退出全屏触发 | () => void | - |
| onEnter | 全屏触发 | () => void | - |
Result
返回的结果如下:
| 参数 | 说明 | 类型 |
|---|---|---|
| isFullscreen | 是否全屏 | boolean |
| enterFullscreen | 设置全屏 | () => void |
| exitFullscreen | 退出全屏 | () => void |
| toggleFullscreen | 切换全屏 | () => void |
| isEnabled | 是否支持全屏 | boolean |
接下来 看下 用法
基本用法
使用 ref 设置需要全屏的元素
import React, { useRef } from 'react';
import { useFullscreen } from 'ahooks';
export default () => {
const ref = useRef(null);
const [isFullscreen, { enterFullscreen, exitFullscreen, toggleFullscreen }] = useFullscreen(ref);
return (
<div ref={ref} style={{ background: 'white' }}>
<div style={{ marginBottom: 16 }}>{isFullscreen ? 'Fullscreen' : 'Not fullscreen'}</div>
<div>
<button type="button" onClick={enterFullscreen}>
enterFullscreen
</button>
<button type="button" onClick={exitFullscreen} style={{ margin: '0 8px' }}>
exitFullscreen
</button>
<button type="button" onClick={toggleFullscreen}>
toggleFullscreen
</button>
</div>
</div>
);
};
图片全屏
import React from 'react';
import { useFullscreen } from 'ahooks';
import img from './react-hooks.jpg';
export default () => {
const [, { enterFullscreen }] = useFullscreen(() => document.getElementById('fullscreen-img'));
return (
<div style={{ background: 'white' }}>
<div style={{ marginBottom: 16 }}>
<img id="fullscreen-img" src={img} style={{ width: 320 }} alt="" />
</div>
<button type="button" onClick={enterFullscreen}>
enterFullscreen
</button>
</div>
);
};
接下来一起看下 源码
源码
1.定义 传入的 目标元素的 类型
target: BasicTarget
export type BasicTarget<T extends TargetType = Element> =
| (() => TargetValue<T>)
| TargetValue<T>
| MutableRefObject<TargetValue<T>>;
2.定义传入的配置项的类型
options?: Options
export interface Options {
onExit?: () => void;
onEnter?: () => void;
}
3.通过props options拿到 配置项的两个函数,然后通过 useLatest包裹这两个函数,使得一直处于最新的函数
const { onExit, onEnter } = options || {};
const onExitRef = useLatest(onExit);
const onEnterRef = useLatest(onEnter);
4.定义 state 表示是否全屏的状态,初始值为false
const [state, setState] = useState(false);
5.编写 设置成全屏的函数,这里使用 screenfull 这个第三方库。首先获取目标元素,如果没有获取到目标元素,则直接return。然后判断screenfull.isEnabled是否全屏,如果是的话,则执行onChange函数
import screenfull from 'screenfull';
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);
}
}
};
6.接下来看下onChange函数。首先判断screenfull.isEnabled是否处于全屏状态,如果是的话,获取目标元素,然后判断screenfull.element不存在的时候,表示退出全屏,则执行退出全屏的函数,并将state设置成false,否则设置成true
const onChange = () => {
if (screenfull.isEnabled) {
const el = getTargetElement(target);
if (!screenfull.element) {
onExitRef.current?.();
setState(false);
screenfull.off('change', onChange);
} else {
const isFullscreen = screenfull.element === el;
if (isFullscreen) {
onEnterRef.current?.();
} else {
onExitRef.current?.();
}
setState(isFullscreen);
}
}
};
7.同理退出全屏的方法
const exitFullscreen = () => {
const el = getTargetElement(target);
if (screenfull.isEnabled && screenfull.element === el) {
screenfull.exit();
}
};
8.最后返回结果
return [
state,
{
enterFullscreen: useMemoizedFn(enterFullscreen),
exitFullscreen: useMemoizedFn(exitFullscreen),
toggleFullscreen: useMemoizedFn(toggleFullscreen),
isEnabled: screenfull.isEnabled,
},
] as const;