ahooks源码分析-useFullscreen

2,037 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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个参数是配置的参数

参数说明类型默认值
targetDOM 节点或者 refElement | () => 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>
  );
};

image.png

图片全屏

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>
  );
};

image.png

接下来一起看下 源码

源码

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;

其他hooks

useLatest

useEventListener

useClickAway

useDocumentVisibility

useTitle