大家都能看得懂的源码 - 那些关于DOM的常见Hook封装(二)
本文是深入浅出 ahooks 源码系列文章的第十五篇,该系列已整理成文档-地址。觉得还不错,给个 star 支持一下哈,Thanks。
本篇接着针对关于 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,根据当前状态,调用上面两个方法,达到切换全屏状态的效果。
// 切换模式
const toggleFullscreen = () => {
if (state) {
exitFullscreen();
} else {
enterFullscreen();
}
};
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;
}
本文已收录到个人博客中,欢迎关注~
大家都能看得懂的源码 - 那些关于DOM的常见Hook封装(二)的更多相关文章
- 大家都能看得懂的源码 - 那些关于DOM的常见Hook封装(一)
本文是深入浅出 ahooks 源码系列文章的第十四篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 上一篇我们探讨了 ahooks 对 DOM 类 Hooks 使用 ...
- 大家都能看得懂的源码 - ahooks useSet 和 useMap
本文是深入浅出 ahooks 源码系列文章的第十篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 今天我们来聊聊 ahooks 中对 Map 和 Set 类型进行状 ...
- 大家都能看得懂的源码(一)ahooks 整体架构篇
本文是深入浅出 ahooks 源码系列文章的第一篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 第一篇主要介绍 ahooks 的背景以及整体架构. React h ...
- 大家都能看得懂的源码 - 如何封装 cookie/localStorage/sessionStorage hook?
本文是深入浅出 ahooks 源码系列文章的第九篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 今天来看看 ahooks 是怎么封装 cookie/localSt ...
- 大家都能看得懂的源码 - ahooks 是怎么处理 DOM 的?
本文是深入浅出 ahooks 源码系列文章的第十三篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 本篇文章探讨一下 ahooks 对 DOM 类 Hooks 使用 ...
- 大家都能看得懂的源码之ahooks useInfiniteScroll
本文是深入浅出 ahooks 源码系列文章的第十七篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 简介 useInfiniteScroll 封装了常见的无限滚动逻 ...
- 大家都能看得懂的源码之 ahooks useVirtualList 封装虚拟滚动列表
本文是深入浅出 ahooks 源码系列文章的第十八篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 简介 提供虚拟化列表能力的 Hook,用于解决展示海量数据渲染时 ...
- 如何读懂Framework源码?如何从应用深入到Framework?
如何读懂Framework源码? 首先,我也是一个应用层开发者,我想大部分有"如何读懂Framework源码?"这个疑问的,应该大都是应用层开发. 那对于我们来讲,读源码最大的问题 ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
随机推荐
- Redis 中的事务分析,Redis 中的事务可以满足ACID属性吗?
Redis 中的事务 什么是事务 1.原子性(Atomicity) 2.一致性(Consistency) 3.隔离性(Isolation) 4.持久性(Durability) 分析下 Redis 中的 ...
- Sublime Text 新建代码片段(图解)
新建代码片段 1.打开NEW Snippet- 2.编辑代码片段 3.设置快捷键,按tab键执行 更多内容请见原文,原文转载自:https://blog.csdn.net/weixin_4451949 ...
- 关于Vue Element组件el-checkbox与el-select默认选中值的几点注意事项
el-select 示例: 代码: <el-select v-model="doc.zhic" placeholder="请选择"> <el- ...
- Linux 文件的打包压缩
压缩和解压 压缩:为了节约磁盘空间. gzip --- .gz bzip2 --- .bz2 xz --- .xz compress --- .z 压缩比例:xz > bzip2 > gz ...
- 小样本利器2.文本对抗+半监督 FGSM & VAT & FGM代码实现
小样本利器2.文本对抗+半监督 FGSM & VAT & FGM代码实现 上一章我们聊了聊通过一致性正则的半监督方案,使用大量的未标注样本来提升小样本模型的泛化能力.这一章我们结合FG ...
- [.NET6]使用ML.NET+ONNX预训练模型整活B站经典《华强买瓜》
最近在看微软开源的机器学习框架ML.NET使用别人的预训练模型(开放神经网络交换格式.onnx)来识别图像,然后逛github发现一个好玩的repo.决定整活一期博客. 首先还是稍微科普一下机器学习相 ...
- .Net之延迟队列
介绍 具有队列的特性,再给它附加一个延迟消费队列消息的功能,也就是说可以指定队列中的消息在哪个时间点被消费. 使用场景 延时队列在项目中的应用还是比较多的,尤其像电商类平台: 订单成功后,在30分钟内 ...
- Ubuntu 隐藏所有窗口快捷键不生效问题
在绑定界面卡住时,切换到一个tty窗口,再切回来 gsettings reset-recursively org.gnome.settings-daemon.plugins.media-keys gs ...
- Vue中关于this指向的问题
由Vue管理的函数 例如: computed 计算属性 watch 监视属性 filters (Vue3中已弃用且不再支持) 过滤器 .... 上述属性里配置的函数不要采用箭头函数写法,因为箭头函数没 ...
- 2022-07-25 第四组 java之抽象、接口
目录 一.抽象类 1.概念 2.抽象类以及抽象方法格式定义 3.抽象类总结规定 二.接口 1.什么是接口 2.接口的定义 3.接口特性 4.抽象类和接口的区别 5.继承抽象类和实现接口的异同 6.规则 ...