antd-mobile
Version:
<img src="https://gw.alipayobjects.com/mdn/rms_ee68a8/afts/img/A*hjjDS5Yy-ooAAAAAAAAAAAAAARQnAQ" alt="logo" width="100%" />
69 lines (59 loc) • 1.84 kB
JavaScript
import { useTouch } from './use-touch';
import { useEffect } from 'react';
import { getScrollParent } from './get-scroll-parent';
import { supportsPassive } from './supports-passive';
let totalLockCount = 0;
const BODY_LOCK_CLASS = 'adm-overflow-hidden'; // 移植自vant:https://github.com/youzan/vant/blob/HEAD/src/composables/use-lock-scroll.ts
export function useLockScroll(rootRef, shouldLock) {
const touch = useTouch();
const onTouchMove = event => {
touch.move(event);
const direction = touch.deltaY.current > 0 ? '10' : '01';
const el = getScrollParent(event.target, rootRef.current);
if (!el) return;
const {
scrollHeight,
offsetHeight,
scrollTop
} = el;
let status = '11';
if (scrollTop === 0) {
status = offsetHeight >= scrollHeight ? '00' : '01';
} else if (scrollTop + offsetHeight >= scrollHeight) {
status = '10';
}
if (status !== '11' && touch.isVertical() && !(parseInt(status, 2) & parseInt(direction, 2))) {
if (event.cancelable) {
event.preventDefault();
}
}
};
const lock = () => {
document.addEventListener('touchstart', touch.start);
document.addEventListener('touchmove', onTouchMove, supportsPassive ? {
passive: false
} : false);
if (!totalLockCount) {
document.body.classList.add(BODY_LOCK_CLASS);
}
totalLockCount++;
};
const unlock = () => {
if (totalLockCount) {
document.removeEventListener('touchstart', touch.start);
document.removeEventListener('touchmove', onTouchMove);
totalLockCount--;
if (!totalLockCount) {
document.body.classList.remove(BODY_LOCK_CLASS);
}
}
};
useEffect(() => {
if (shouldLock) {
lock();
return () => {
unlock();
};
}
}, [shouldLock]);
}