背景
日常开发中为了提高开发效率,实现逻辑分离。开发了很多自定义hooks,开发过程很烧脑,开发过后,很爽。
功能
1. 记录页面浏览时长
import useDeepCompareEffect from 'use-deep-compare-effect';
import dayjs from 'dayjs';
const logRequest = (name, params) => {
// 发送的具体请求内容
...
}
const FORMAT_TIME = (time) => dayjs(Number(time)).format('YYYY-MM-DD HH:mm:ss');
export default function usePageDuration(name, params) {
useDeepCompareEffect(() => {
if (params.agentId_var) {
const startTimeKey = `${name}-startTime`;
const endTimeKey = `${name}-endTime`;
const paramsKey = `${name}-params`;
// 1. 先判断上次有没有访问过页面(有没有startTime 和 endTime)有的话则发送请求
const checkLastTime = () => {
const startTime = localStorage.getItem(startTimeKey);
const endTime = localStorage.getItem(endTimeKey);
if (startTime && endTime) {
const lastParams = JSON.parse(localStorage.getItem(paramsKey));
const { completionRate_var: rateVar, ...others } = lastParams;
// 记录上次进入页面的时间
logRequest(name, {
...others,
startTime_var: FORMAT_TIME(startTime),
});
// 记录上次页面消失的时间
if (rateVar) {
// 页面包含图片,需要等图片基本加载完后再获取页面总高document.body.scrollHeight,测试过不缓存,高速3G情况下,2s可加载所有图片,故设置2s定时
setTimeout(() => {
// 阅读速度: 20px/1s (每秒读20像素的高度), 因为算的是百分比,所以乘以100, 速度定为2000。
const speed = 2000;
const durationTime = Math.ceil((endTime - startTime) / 1000); // x 秒
const readHight = durationTime * speed;
const rate = Math.ceil(readHight / document.body.scrollHeight);
lastParams.completionRate_var = `${rate > 100 ? 100 : rate}%`;
logRequest(name, {
...lastParams,
endTime_var: FORMAT_TIME(endTime),
});
}, 2000);
} else {
logRequest(name, {
...lastParams,
endTime_var: FORMAT_TIME(endTime),
});
}
localStorage.setItem(startTimeKey, '');
localStorage.setItem(endTimeKey, '');
localStorage.setItem(paramsKey, '');
}
};
checkLastTime();
// 2. 记录本次浏览的开始时间
localStorage.setItem(startTimeKey, new Date().getTime());
// 3. 记录本次浏览的结束时间和对应参数
const pagehideFn = () => {
localStorage.setItem(endTimeKey, new Date().getTime());
localStorage.setItem(paramsKey, JSON.stringify(params));
};
window.addEventListener('pagehide', pagehideFn);
return () => {
pagehideFn();
window.removeEventListener('pagehide', pagehideFn);
};
}
}, [name, params]);
}
2. 页面有弹窗时,禁止主页面滚动条滚动
import { useEffect } from 'react';
const usePreventScroll = (visible) => {
useEffect(() => {
let ele = document.querySelector('html');
const { body } = document;
if (visible) {
ele.style.overflow = 'hidden';
body.style.overflow = 'hidden';
} else {
ele.style.overflow = 'initial';
body.style.overflow = 'initial';
}
return () => {
ele = null;
};
}, [visible]);
};
export default usePreventScroll;
3. 滚动条是否触底
import { useState, useEffect } from 'react';
import _ from 'lodash';
/**
*
* @param reactionDistance 距离底部的触发距离,默认为0
*/
const useTouchBottom = (reactionDistance = 0) => {
const [touchBottom, setTouchBottom] = useState(false);
useEffect(() => {
// 页面已经滚动的距离
const getScrollTop = () => {
const bodyScrollTop = document.body?.scrollTop || 0;
const documentScrollTop = document.documentElement?.scrollTop || 0;
return bodyScrollTop > documentScrollTop ? bodyScrollTop : documentScrollTop;
};
// 页面dom总高
const getScrollHeight = () => {
const bodyScrollHeight = document.body?.scrollHeight || 0;
const documentScrollHeight = document.documentElement?.scrollHeight || 0;
return bodyScrollHeight > documentScrollHeight ? bodyScrollHeight : documentScrollHeight;
};
// 当前窗口的高度
const getWindowHeight = () => {
return document.compatMode === 'CSS1Compat' ? document.documentElement.clientHeight : document.body.clientHeight;
};
const handleScroll = () => {
setTouchBottom(getScrollHeight() - getScrollTop() - getWindowHeight() <= reactionDistance);
};
const scrollFn = _.throttle(handleScroll, 100);
window.addEventListener('scroll', scrollFn);
return () => {
window.removeEventListener('scroll', scrollFn);
};
}, [reactionDistance]);
return touchBottom;
};
export default useTouchBottom;
4. 滚动条是否触顶
import { useState, useEffect } from 'react';
import _ from 'lodash';
export default function useTouchTop(ele) {
const [touchTop, setTouchTop] = useState(false);
useEffect(() => {
if (ele) {
const handleScroll = () => {
// js scrollIntoView 后top为0.00xxx;所以设置值为1
setTouchTop(ele.getBoundingClientRect().top <= 1);
};
const scrollFn = _.throttle(handleScroll, 100);
window.addEventListener('scroll', scrollFn);
return () => {
window.removeEventListener('scroll', scrollFn);
};
}
}, [ele]);
return touchTop;
}