禁用特定页面的滚动

7

有没有办法在单个页面上禁用滚动?我尝试在特定页面上设置overflow: hidden,但没有效果。我必须在index.css的body上设置它才能生效,但这会禁用所有页面的滚动。所以我想到的唯一方法是基于Redux存储中的值有条件地在body上设置CSS类。是否有办法在index.js中根据Redux存储中的值有条件地设置CSS类,或者是否有其他方法?

我的 index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {BrowserRouter} from 'react-router-dom'
import {Provider} from 'react-redux'
import {createStore,applyMiddleware,compose,combineReducers} from "redux";
import thunk from 'redux-thunk'
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import authReducer from './store/reducers/auth'

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const rootReducer = combineReducers({
   auth: authReducer
})

const store = createStore(rootReducer,
   composeEnhancers(applyMiddleware(thunk)));

const app =(
   <Provider store={store}>
      <BrowserRouter>
         <App/>
      </BrowserRouter>
   </Provider>
)

ReactDOM.render(
  <React.StrictMode>
     {app}
  </React.StrictMode>,
  document.getElementById('root')
);
serviceWorker.unregister();

@xKobalt Reacts 是一个单页应用程序,因此如果我在 body 上设置 overflow: hidden,则所有其他“页面”都会受到影响,因为它们使用相同的 body。 - delmin
@xKobalt 到目前为止,我的应用有两个页面.. 登录和主页... 当用户未登录且在redux存储中使用令牌属性时,我需要禁用登录页面上的滚动.. 因此,如果令牌可用,则使用一种类别,否则使用另一种类别。 - delmin
那么...以下可能是一个解决方案吗?-使用一个变量来获取标题页面,然后进行比较,如果它代表登录页面,那么添加有关会话的控件(因此,如果用户已登录,则应显示没有限制的正文,否则应在正文中添加所述属性)。 - xKobalt
也许您可以为特定页面添加一个ID,并编写一个函数,如果它找到该ID,则会从body元素中删除类名? - Frontend employee
@xKobalt 嗯,是的...我正在尝试做这个,但问题在于我认为只有在index.js中才能实现它。要在index.js中实现它,我必须从redux全局存储中获取将要比较的值。但是我不确定是否可以从index.js访问redux存储。 - delmin
显示剩余3条评论
6个回答

7

如果你想在 body 上设置样式,可以在页面上运行以下代码,将禁用滚动。

document.body.style.overflow='hidden'

然后要重新启用:

document.body.style.overflow='auto'

唯一的缺点是它不太像React。


很好...可以了...非常感谢...那么就不需要条件了吗..太棒了。 - delmin

4

简单的解决方案可能是定义一个特定的class来应用overflow: hidden,并在需要时(例如在显式组件挂载后)将其应用于document.body

.overflow-hidden {
   overflow: hidden;
}

在特定页面挂载时调用:
document.body.classList.add("overflow-hidden");

或者你可以直接分配属性

document.body.style.overflow = "hidden";

是的,谢谢。那就是我在寻找的东西。谢谢。 - delmin

2

您可以将组件包裹在另一个div中,并为该包装器div设置overflow:hidden;样式,可能还需要添加max-height: 70vh;以确保它不超过页面的末尾。

div {
  padding: .5rem;
  margin: .5rem
}

.no-scroll-wrapper {
  max-height: 70vh;
  overflow: hidden;
  background-color: darkgrey;
  padding: 1rem;
}

.large-inner {
  height: 1000px;
  background-color: grey
}
<body>
  <div class="no-scroll-wrapper">
    wrapper element disables scrolling
    <div class="large-inner">
      Content here, very long div, but you can't see the end of it.
    </div>
  </div>
  </body


1
谢谢你的回答。问题就像我所说的,React是单页应用程序,因此所有页面都共享body。我将不得不进行一些条件选择body类或overflow属性何时触发它,因为我只想在一个“页面”上禁用滚动...虽然我真的不知道如何在React中实现它。 - delmin
我在.NET中使用Blazor作为SPA框架,效果非常完美。谢谢! - Jeffrey Padgett

1
补充 Luke Storrymidnightgamer 出色的答案。您可以使用自定义的React Hook与useEffect一起使用,而不必在每个页面中添加document.body.style.overflow='auto'来重新启用滚动。
import { useEffect } from 'react'

const useOverFlowHidden = () => {
    useEffect(() => {
        document.body.style.overflow = 'hidden'

        return () => {
            document.body.style.overflow = 'auto' // cleanup or run on page unmount
        }
    }, [])
}

export default useOverFlowHidden

使用方法:

const Page = () => {
    useOverFlowHidden(); // use on pages you want to disable overflow/scroll
    return <></>;
}

1
一个简单的解决方案可能是定义一个特定的类来应用overflow: hidden,并在需要时将其应用于文档。每当你想要离开页面时,从body中删除该类即可。
.overflow-hidden {
   overflow: hidden;
}

在特定页面上为body附加类,并在离开页面时删除,以免影响其他页面。
useEffect(() => {
        document.body.classList.add("overflow-hidden");
        return () => {
            document.body.classList.remove("overflow-hidden");
        };
 }, []);

当您离开页面时,这将简单地从主体中删除类。

0

我使用 body-scroll-lock npm 包:

import {disableBodyScroll,enableBodyScroll,clearAllBodyScrollLocks} from "body-scroll-lock"

const YourPage=(props)=>{
     const ref=useRef(null)

     useEffect(() => {
         if (ref.current) {
             // you might add a condition to lock the scroll
             if (conditionIsTrue) {
                   disableBodyScroll(ref.current)
             } else {
             enableBodyScroll(ref.current)
                }
             }
             return () => {
                  clearAllBodyScrollLocks()
                   }    
      },[addDependencyHere])         

     return(
       <div ref={ref}>
       ....
       </>
     )
}
  • 从上述npm包的文档中,您也可以使用纯js来采用这种方法。不建议直接在react.js中访问document对象

       document.body.ontouchmove = (e) => { 
           e.preventDefault(); 
           return false;
    
  • 在触摸屏设备上,您可以有条件地设置此CSS类以防止滚动

    touch-action:none
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接