我想让我的身体在使用鼠标滚轮时停止滚动,而我的网站上的Modal(来自http://twitter.github.com/bootstrap)是打开的。

当模式被打开时,我试图调用下面的javascript片段,但没有成功

$(window).scroll(function() { return false; });

AND

$(window).live('scroll', function() { return false; });

请注意,我们的网站放弃了对IE6的支持,IE7+需要兼容。


当前回答

我必须设置视口高度才能让它完美工作

body.modal-open {
  height: 100vh;
  overflow: hidden;
}

其他回答

警告:下面的选项与Bootstrap v3.0无关。X,因为在这些版本中滚动被显式地限制在模态本身。如果禁用轮事件,可能会无意中阻止一些用户在高度大于视口高度的模态中查看内容。


还有另一个选择:车轮事件

滚动事件不可取消。但是,可以取消鼠标滚轮和滚轮事件。需要注意的是,并不是所有的传统浏览器都支持它们,Mozilla最近才在Gecko 17.0中添加了对后者的支持。我不知道它们的全部分布,但IE6+和Chrome确实支持它们。

下面是如何利用它们的方法:

$('#myModal')
  .on('shown', function () {
    $('body').on('wheel.modal mousewheel.modal', function () {
      return false;
    });
  })
  .on('hidden', function () {
    $('body').off('wheel.modal mousewheel.modal');
  });

JSFiddle

当你在另一个模态中使用一个模态时,就会发生上述情况。当我在另一个模态中打开一个模态时,后者的关闭将从主体中移除类modal-open。这个问题的解决取决于你如何关闭后一个模式。

如果你用html关闭模态,

<button type="button" class="btn" data-dismiss="modal">Close</button>

然后你必须像这样添加一个监听器,

$(modalSelector).on("hidden.bs.modal", function (event) {
    event.stopPropagation();
    $("body").addClass("modal-open");
    return false;
});

如果你用javascript关闭模态,

$(modalSelector).modal("hide");

然后你必须在一段时间后像这样运行命令,

setInterval(function(){$("body").addClass("modal-open");}, 300);

我读的大多数答案都是关于React的。

我的React功能组件的最佳解决方案是使用@arcticmatt最初提供的解决方案

我在下面的代码示例中包含了一些在其他答案中提到的改进(注意useEffect定义):

import {useEffect, useRef} from "react";

export default function PopoverMenu({className, handleClose, children}) {
  const selfRef = useRef(undefined);

  useEffect(() => {
    const isPopoverOpenned = selfRef.current?.style.display !== "none";
    const focusedElement = document?.activeElement;
    const scrollPosition = {x: window.scrollX, y: window.scrollY};
    if (isPopoverOpenned) {
      preventDocBodyScrolling();
    } else {
      restoreDocBodyScrolling();
    }

    function preventDocBodyScrolling() {
      const width = document.body.clientWidth;
      const hasVerticalScrollBar = (window.innerWidth > document.documentElement.clientWidth);
      document.body.style.overflowX = "hidden";
      document.body.style.overflowY = hasVerticalScrollBar ? "scroll" : "";
      document.body.style.width = `${width}px`;
      document.body.style.position = "fixed";

    }

    function restoreDocBodyScrolling() {
      document.body.style.overflowX = "";
      document.body.style.overflowY = "";
      document.body.style.width = "";
      document.body.style.position = "";
      focusedElement?.focus();
      window.scrollTo(scrollPosition.x, scrollPosition.y);
    }


    return () => {
      restoreDocBodyScrolling(); // cleanup on unmount
    };
  }, []);

  return (
    <>
      <div
        className="backdrop"
        onClick={() => handleClose && handleClose()}
      />
      <div
        className={`pop-over-menu${className ? (` ${className}`) : ""}`}
        ref={selfRef}
      >
        <button
          className="pop-over-menu--close-button" type="button"
          onClick={() => handleClose && handleClose()}
        >
          X
        </button>
        {children}
      </div>
    </>
  );
}

这是

body.modal-open {
   overflow: hidden !important;
}

这是TypeScript中的一种解决方案,可以轻松地阻止事件扩展,也可以处理移动设备。当禁用垂直滚动条时,这也不会导致水平跳转。 只需使用底部的导出函数,例如任何HTML元素上的onclick处理程序。如果不是在NodeJS环境中运行,只需删除该进程。客户端检查。

/**
 * Handles scroll events for modal content
 */

const events = [
  'DOMMouseScroll',
  'mousewheel',
  'wheel',
  'touchmove',
  'keydown',
  'mousedown',
  'scroll',
];

const preventDefault = (e: Event) => {
  e.preventDefault();
  e.stopPropagation();
  return false;
};

let currentY: number;

const disableScroll = () => {
  currentY = window.scrollY;

  events.forEach((event) => {
    window.addEventListener(event, preventDefault, {
      passive: false,
    });
  });

  const bodyStyle = document.body.style;
  bodyStyle.setProperty('touch-action', 'none');
  bodyStyle.setProperty('position', 'fixed');
  bodyStyle.setProperty('overflow-y', 'scroll');
  bodyStyle.setProperty('width', '100%');
  bodyStyle.setProperty('top', `-${currentY}px`);
};

const enableScroll = () => {
  events.forEach((event) => {
    window.removeEventListener(event, preventDefault);
  });

  const bodyStyle = document.body.style;
  bodyStyle.removeProperty('touch-action');
  bodyStyle.removeProperty('position');
  bodyStyle.removeProperty('overflow-y');
  bodyStyle.removeProperty('width');
  bodyStyle.removeProperty('top');
  window.scroll(0, currentY);
};

/**
 * Makes a component (e.g. popup) modal
 */
export const makeModal = () => {
  if (process.client) {
    disableScroll();
  }
};

/**
 * Makes a component (e.g. popup) non-modal
 */
export const makeNonModal = () => {
  if (process.client) {
    enableScroll();
  }
};