自定义hooks

背景

日常开发中为了提高开发效率,实现逻辑分离。开发了很多自定义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;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容