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);
}
}