防止在 React 渲染组件上使用 CSS 滚动

Posted

技术标签:

【中文标题】防止在 React 渲染组件上使用 CSS 滚动【英文标题】:Prevent scrolling using CSS on React rendered components 【发布时间】:2017-02-19 03:21:09 【问题描述】:

所以我在html 中通过 React 渲染一个组件,如下所示:

 <html>
  <body>
    <div id=app>$appHtml</div>
    <script src="/bundle.js"></script>
  </body>
</html>

在我的应用中,我有一个汉堡按钮,onClick 会全屏显示。

但是,正文是可滚动的。我通常会在body 标签中添加一个类并使其成为overflow: hidden 以防止这种情况。但是,我的反应组件在 body 标记内呈现,因此我无法控制基于反应组件内的单击来切换类。

有没有人对我如何实现我正在寻找的东西有任何想法/建议。

谢谢!

【问题讨论】:

When, where and how to add class to the document.body when using React.js的可能重复 链接:-npmjs.com/package/react-sticky 【参考方案1】:

“我无法控制基于反应组件中的点击来切换类。”

不一定是真的!

您以“React-ful”的方式思考并且对修改 DOM 保持警惕,这很好。你想要避免进行 DOM 操作的主要原因是它会导致 React 尝试渲染的内容与你可能尝试进行的未知更改之间发生冲突。但在这种情况下,你不是在操作 React 正在渲染的 DOM,而是在操作它的 parent。在这种情况下,你可以做这样的事情:

document.body.style.overflow = "hidden"

或者

document.body.classList.add("no-scroll")

或任何有效的方法。你是完全安全的,因为 React 只在 #app 内渲染 DOM,并不关心它的父级中发生了什么。事实上,许多应用程序和网站仅在页面的一小部分使用 React,以呈现单个组件或小部件,而不是整个应用程序。

除此之外,还有一种更好、更“React-ful”的方式来做你想做的事。只需重新构建您的应用程序,使滚动容器位于您的 React 应用程序中,而不是 body。结构可能如下所示:

<html>
  <body>
    <div id="app">
      <div id="scroll-container">
        <!-- the rest of your app -->
      </div>
    </div>
  </body>
</html>

使body溢出隐藏,body#app填满整个屏幕,你可以控制#scroll-container是否允许滚动或不完全在React中。

【讨论】:

谢谢你!我实际上认为如果您尝试更改其组件之外的任何内容,react 只会抱怨。我从来不知道你还能做到这一点。 nextjs 上没有 dom【参考方案2】:

我建议使用 css position: "sticky" ,但我想这不是这里所质疑的。但它对我有用。我猜其他解决方案更好。

【讨论】:

答案形式的评论。【参考方案3】:

这是我的两分钱:您可以将包含您的内容的 div 的高度设置为 100%(高度:100%) 或者在这种情况下 body height: 100%

【讨论】:

【参考方案4】:

这里是如何在 reactjs 中使用 body-scroll-lock 库...

import React, useState from 'react';
import  disableBodyScroll, enableBodyScroll  from 'body-scroll-lock';

// Components
import Hamburger from './HeaderComponents/Hamburger.js';
import MegaDropdown from './HeaderComponents/MegaDropdown.js';

const Header = props => 
  // variables
  const [isSideNavShown, setIsSideNavShown] = useState(false);
  const [isDropdownShowing, setIsDropdownShowing] = useState(false);

  isDropdownShowing ? disableBodyScroll(document) : enableBodyScroll(document)

  return (
    <header className="header">
      <Hamburger isDropdownShowing=isDropdownShowing setIsDropdownShowing=setIsDropdownShowing />
      <MegaDropdown isDropdownShowing=isDropdownShowing setIsDropdownShowing=setIsDropdownShowing />
    </header>
  )


export default Header;

尤其是isDropdownShowing ? disableBodyScroll(document) : enableBodyScroll(document)这一行

这允许当我的下拉列表中的内容填充到需要向其添加滚动的点时,在显示下拉列表时禁用窗口(正文)滚动(覆盖我的整个屏幕)。所以即使窗口(正文)滚动被禁用,我仍然可以滚动浏览我的下拉菜单。

【讨论】:

【参考方案5】:

以上不适用于 ios 移动设备。

body-scroll-lock 结合使用 CSS 和 JS 使其适用于所有设备,同时保持目标元素(例如模式)的可滚动性。

即。对于 iOS,需要检测何时到达目标元素的底部或顶部,然后完全停止滚动

【讨论】:

这如何回答 OP 的问题? body-scroll-lock 是否允许您阻止父元素在其子元素一直向下滚动到底部或顶部时滚动? @RaulSauco 我不得不自己尝试一下,看看我在这个问题中的答案。 @tonix 是的,看看我的回答。

以上是关于防止在 React 渲染组件上使用 CSS 滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 react 重新渲染整个组件?

React Native this.setState() 仅在再次与组件交互后重新渲染

如何防止我的功能组件使用 React 备忘录或 React 钩子重新渲染?

使用 setInterval 时如何防止 React 重新渲染整个组件

React Hook 功能组件防止重新渲染

React:如何防止在`map`中重新渲染子组件?