锁定正文滚动,阻止目标元素滚动

Posted

技术标签:

【中文标题】锁定正文滚动,阻止目标元素滚动【英文标题】:Locking the body scroll, blocks target element scrolling 【发布时间】:2021-04-09 00:51:45 【问题描述】:

我正在使用以下库来锁定页面主体的滚动,并且只允许在我的模式打开时滚动。

https://www.npmjs.com/package/body-scroll-lock

我的模态AddItemModal 是一个门户,所以在index.html 文件中我有这个。

<body>
  <div id="root"></div>
  <div id="add-item-modal"></div>
</body>

NavigationIcons 组件(打开模式的地方)

const NavigationIcons = (props) => 
  let targetElement = document.getElementById("add-item-modal");

  useEffect(() => 
    ...
    return () => clearAllBodyScrollLocks();
  , []);

  const renderAddItemModal = () => 
    if (props.addItem) 
      disableBodyScroll(targetElement);
      return <AddItemModal />;
    
  ;

  return (
    <div className="main-4" onClick=() => props.openAddItemModal()>
      renderAddItemModal()
    </div>
  );


AddItemModalHeader 组件(模态关闭的地方)

const AddItemModalHeader = (props) => 
  let targetElement = document.getElementById("add-item-modal");

  return (
    <div className="modal-header">
      add item
      <div className="close" onClick=(e) => 
        props.handleModalClose(e);
        enableBodyScroll(targetElement);
      >
       close
      </div>
    </div>
  )

在文档中写道targetElement 必须是我要显示的模式。但是由于应用程序是在root div 中呈现的,并且模态显示在add-item-modal 中,所以它不应该是root,而是将提供的函数应用于它,例如enableBodyScrolldisableBodyScrollclearAllBodyScrollLocks。我确实尝试了rootadd-item-modal,在这两种情况下,当我从我的 ios 设备进行测试时,滚动都无法在模式上工作。

那里提供的示例并没有让我清楚这一点。有人可以解释我在这里做错了什么吗?

更新

其他可能在 iOS 设备上遇到此问题的人请参阅以下来自 Github 线程的解释清楚的答案 https://github.com/ionic-team/ionic-v1/issues/155#issuecomment-411110252

【问题讨论】:

【参考方案1】:

body-scroll-lock 的一些已知问题是

不适用于 android 网页视图 不能在带有鼠标滚轮的 PC 上工作 在 iOS 上不起作用,如果您触摸某处而不是 targetElement 必须通过 targetElement,即使没有必要

输入tua-body-scroll-lock


请知道我与tua-body-scroll-lock 没有任何联系。


tua-body-scroll-lockbody-scroll-lock 提供的功能相同。喜欢

disableBodyScroll lock 的别名 enableBodyScroll unlock 的别名 clearAllBodyScrollLocks clearBodyLocks 的别名

我使用tua-body-scroll-lock 制作了一个example 的小提琴

你的代码应该是这样的

import lock, unlock, clearBodyLocks from 'tua-body-scroll-lock';

const NavigationIcons = (props) => 
  ...
  useEffect(() => 
    ...
    return () => clearBodyLocks();
  , []);

  const renderAddItemModal = () => 
    if (props.addItem) 
      lock(targetElement);
      return <AddItemModal />;
    
  ;

  ...


const AddItemModalHeader = (props) => 
  return (
    <div className="modal-header">
      add item
      <div className="close" onClick=(e) => 
        props.handleModalClose(e);
        unlock(targetElement);
      >
       close
      </div>
    </div>
  )

【讨论】:

我正在查看您的示例,想知道您从哪里获取 clearBodyLocks 变量。我认为我的问题是我没有针对正确的节点元素,我想更好地了解您做了什么来了解如何使其工作。 clearBodyLocks 函数和你的clearAllBodyScrollLocks 有相同的用途,我将它与lockunlock 函数一起导入了代码的顶部 对不起,我的意思是 bodyScrollLock 来自示例 哦。我在 HTML 中导入了带有script 标记的tua-body-scroll-lock。所以bodyScrollLock 就像拥有lockunlockclearBodyLocks 函数的对象 我编辑了 jsFiddle 以注销 bodyScrollLock 从我编辑的答案中查看新链接【参考方案2】:

如果您查看他们的源代码,disableBodyScroll 在内部所做的唯一事情就是在设备为 IOS 的情况下附加 ontouchstartontouchmove 事件并阻止该事件(通过调用e.preventDefault()) 有条件地如果 targetElement 接近可滚动边界。

所以如果我理解正确的话,targetElement 必须是一个可滚动的元素,否则它永远不会绕过那些边界检查,它会阻止滚动。

在您的情况下,我认为 add-item-modal 不是可滚动元素,因此它不起作用。尝试在模式中使用targetElement 的任何可滚动元素。

【讨论】:

以上是关于锁定正文滚动,阻止目标元素滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止固定元素阻止滚动页面?

如何阻止我的 body 元素在导航栏后面滚动?

无法阻止“touchmove”在 iOS 上滚动窗口

由于目标被视为被动,无法在被动事件侦听器中阻止默认值?为啥滚动时出现此错误?

scroll时怎么阻止body页面的滚动

js 弹出框 里面元素touchmove时候阻止其他元素滚动,背景遮罩层还无法阻止冒泡,怎么禁用遮罩层touchmove