h5实现下拉刷新

2022-10-27  本文已影响0人  芸芸众生ing

interface State {
  pageX: number,
  pageY: number,
  isMove: boolean,
  moveHeight: number,
  step: number
}
interface Options {
  callback?: Function, // 下拉刷新回调函数
  stepCallback?: Function, // 当前所在状态
  top?: number, //  距离多远触发刷新
  height?: number, // 刷新是的占位高度
  stepTtext?: [string, string, string, string, string], // 下拉到完成更新的状态语
}

/**
 * 下拉刷新
 * @param selector 选择器或者dom对象
 * @param opts 配置项
 */
export default function (selector: string | any, opts: Options = {}) {
  const { callback, top = 95, height = 30, stepTtext = ['下拉即可刷新', '释放立即刷新', '正在刷新', '刷新完成', '刷新失败'], stepCallback } = opts;
  const AppDom = typeof selector == 'string' ? document.querySelector(selector) : selector;
  const loadingDom = document.createElement('div');
  const state: State = { pageX: 0, pageY: 0, moveHeight: 0, isMove: false, step: 0 };
  const StateProxy = new Proxy(state, {
    set(target, key, value, receiver) {
      if (stepCallback && typeof stepCallback == 'function' && key == 'step') stepCallback(value);
      if (key == 'step') loadingDom.innerText = stepTtext[value];
      return Reflect.set(target, key, value, receiver);
    }
  });
  AppDom?.insertBefore(loadingDom, AppDom.children[0]);
  AppDom?.addEventListener("touchstart", onStartFn);
  AppDom?.addEventListener("touchmove", onMoveFn);
  AppDom?.addEventListener("touchend", onEndFn);
  function onStartFn(event: any) {
    if (StateProxy.isMove) return;
    const pageY = event.touches[0].pageY;
    StateProxy.pageY = pageY;
    loadingDom.setAttribute('style', 'display:flex;justify-content:center;align-items:center;transition:all 0s')
  }
  function onMoveFn(event: any) {
    event.stopPropagation();
    event.preventDefault();
    if (StateProxy.isMove) return;
    const pageY = event.touches[0].pageY;
    const moveHeight = pageY - StateProxy.pageY;
    loadingDom.style.height = moveHeight + "px";
    StateProxy.moveHeight = moveHeight;
    if (moveHeight > 0) {
      StateProxy.step = 0;
      if (moveHeight > top) {
        StateProxy.step = 1;
      }
    }
  }
  function onEndFn() {
    if (StateProxy.isMove) return;
    loadingDom.style.transition = 'all .3s'
    if (StateProxy.moveHeight > top) {
      loadingDom.style.height = height + 'px';
      StateProxy.step = 2;
      insertLoadingDom();
    }

  }
  async function insertLoadingDom() {
    try {
      StateProxy.isMove = true;
      if (callback && typeof callback == 'function') await callback();
      StateProxy.step = 3;
    } catch (error) {
      StateProxy.step = 4;
    }
    closeLoadingDom();
  }
  function closeLoadingDom() {
    loadingDom.style.opacity = '0';
    loadingDom.style.height = '0px';
    const timer = setTimeout(() => {
      clearTimeout(timer);
      StateProxy.pageX = 0;
      StateProxy.pageY = 0;
      StateProxy.step = 0;
      StateProxy.isMove = false;
      StateProxy.moveHeight = 0;
    }, 300);
  }
}
上一篇下一篇

猜你喜欢

热点阅读