use-lock-scroll.mjs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. import { watch, onBeforeUnmount, onDeactivated } from "vue";
  2. import { getScrollParent, onMountedOrActivated } from "@vant/use";
  3. import { useTouch } from "./use-touch.mjs";
  4. import { preventDefault } from "../utils/index.mjs";
  5. let totalLockCount = 0;
  6. const BODY_LOCK_CLASS = "van-overflow-hidden";
  7. function useLockScroll(rootRef, shouldLock) {
  8. const touch = useTouch();
  9. const DIRECTION_UP = "01";
  10. const DIRECTION_DOWN = "10";
  11. const onTouchMove = (event) => {
  12. touch.move(event);
  13. const direction = touch.deltaY.value > 0 ? DIRECTION_DOWN : DIRECTION_UP;
  14. const el = getScrollParent(
  15. event.target,
  16. rootRef.value
  17. );
  18. const { scrollHeight, offsetHeight, scrollTop } = el;
  19. let status = "11";
  20. if (scrollTop === 0) {
  21. status = offsetHeight >= scrollHeight ? "00" : "01";
  22. } else if (scrollTop + offsetHeight >= scrollHeight) {
  23. status = "10";
  24. }
  25. if (status !== "11" && touch.isVertical() && !(parseInt(status, 2) & parseInt(direction, 2))) {
  26. preventDefault(event, true);
  27. }
  28. };
  29. const lock = () => {
  30. document.addEventListener("touchstart", touch.start);
  31. document.addEventListener("touchmove", onTouchMove, { passive: false });
  32. if (!totalLockCount) {
  33. document.body.classList.add(BODY_LOCK_CLASS);
  34. }
  35. totalLockCount++;
  36. };
  37. const unlock = () => {
  38. if (totalLockCount) {
  39. document.removeEventListener("touchstart", touch.start);
  40. document.removeEventListener("touchmove", onTouchMove);
  41. totalLockCount--;
  42. if (!totalLockCount) {
  43. document.body.classList.remove(BODY_LOCK_CLASS);
  44. }
  45. }
  46. };
  47. const init = () => shouldLock() && lock();
  48. const destroy = () => shouldLock() && unlock();
  49. onMountedOrActivated(init);
  50. onDeactivated(destroy);
  51. onBeforeUnmount(destroy);
  52. watch(shouldLock, (value) => {
  53. value ? lock() : unlock();
  54. });
  55. }
  56. export {
  57. useLockScroll
  58. };