背景
偶然间,在使用一款google插件的时候,发现它有一个小功能,只要我停留在它的页面不操作10分钟以上,就会自动给我打开一个屏保界面,这样的
目的
这种华而不实的功能,正好适合个人博客,所以我就自己简单实现了一下
核心思路
监听用户当前是否出于活跃状态,这里的活跃状态包含以下几种
- 是否出发滚动;
- 是否移动或者点击鼠标;
- 是否按下键盘;
- 是否离开(或隐藏)当前窗口(可选)
监听用户以上的事件,来判断是否在一段时间内,用户是处于活跃状态的
下面useListenPage的hook中,会监听以上几种事件
代码如下
代码其实就很简单了,这里我直接写了一个hook,方便后续扩展和使用。
hooks的功能:在一段时间内,返回用户是否活跃状态的布尔值
import { useState } from "react";
import { useMount } from "./useMount";
import { useUnMount } from "./useUnMount";
import { debounce } from '../utils';
const defaultDelay = 10000;
interface IUseListenPage {
/** 空闲时间, 默认10s不操作就进入不活跃状态 */
delay?: number;
/** 是否页面不可见时,设置为不活跃 */
isHidden?: boolean;
}
export function useListenPage(props: IUseListenPage) {
const { delay = defaultDelay, isHidden = false } = props;
const [isActive, setIsActive] = useState(true);
let timer: any = null;
const startListener = () => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
if (isActive) {
setIsActive(false);
}
}, delay);
}
const handleAction = () => {
setIsActive(true);
/** 重新开启监听 */
startListener();
}
const handleVisibilityChange = () => {
if (document.hidden && isActive && isHidden) {// 页面不可见时,设置为不活跃
setIsActive(false);
}
}
useMount(() => {
/** 开始监听 */
startListener();
/** 监听页面是否可见 */
window.addEventListener("visibilitychange", handleVisibilityChange)
/** 监听 滚动 鼠标 键盘事件 */
window.addEventListener("scroll", debounce(handleAction));
window.addEventListener("mousemove", debounce(handleAction));
window.addEventListener("keydown", debounce(handleAction));
window.addEventListener("click", debounce(handleAction));
})
useUnMount(() => {
/** 移除监听 */
window.removeEventListener("visibilitychange", handleVisibilityChange)
window.removeEventListener("scroll", debounce(handleAction));
window.removeEventListener("mousemove", debounce(handleAction));
window.removeEventListener("keydown", debounce(handleAction));
window.removeEventListener("click", debounce(handleAction));
})
return isActive;
}
使用如下
function xxx({children}: any) {
const isActive = useListenPage({ delay: 15 * 60 * 1000 });
return isActive ? children : <ScreenSaver />;
}
写在最后
如果觉得这种小知识有帮助到大家,那就点个赞吧,让博主开心开心!
大家有遇到什么问题的,都可以在评论区发出来,只要博主有时间,一定帮你们解决目前的问题,任何相关大前端的疑难杂症都可