我的應(yīng)用程序使用next JS。我的應(yīng)用程序有一個(gè)模態(tài)的標(biāo)志,我想修復(fù)下面的頁(yè)面,使其在打開(kāi)時(shí)不滾動(dòng)。我可以在打開(kāi)模式時(shí)用document . body . style . overflow = ' hidden '來(lái)解決這個(gè)問(wèn)題,但是網(wǎng)站會(huì)跳轉(zhuǎn)到滾動(dòng)條所在的位置。
我想保留滾動(dòng)條,但禁用滾動(dòng)。我在一個(gè)組件中調(diào)用模態(tài),所以像overflow:hidden這樣的CSS屬性只對(duì)相應(yīng)的組件有效。有沒(méi)有一種方法可以讓我實(shí)現(xiàn)我想做的事情?
你可以只在onscroll中添加一個(gè)事件,然后跟蹤當(dāng)前的scrollTop,scrollLeft(如果你也需要處理水平方向的話),然后當(dāng)你不想滾動(dòng)的時(shí)候,只需將scroll重置為這些存儲(chǔ)的值。
例如,如果您在選中大復(fù)選框的情況下運(yùn)行下面的代碼片段,滾動(dòng)將被禁用。
const div = document.querySelector('div');
const cb = document.querySelector('input');
let lastY = 0;
div.innerText = new Array(3000).fill().map(m => 'hello ').join(' ');
div.addEventListener('scroll', (e) => {
if (cb.checked) {
e.target.scrollTop = lastY;
} else lastY = e.target.scrollTop;
});
cb.addEventListener('click', () => {
console.log('click');
});
div {
height: 150px;
overflow: auto;
}
input {
position: fixed;
top: 50px;
left: 50px;
transform: scale(4);
}
<div>
</div>
<input type="checkbox"/>
唷。花了很多時(shí)間挖掘(博客和人工智能[不是StackOverflow答案本身,特別是這里沒(méi)有接受的答案]似乎奇怪地滿足于簡(jiǎn)單地讓滾動(dòng)條暫時(shí)完全消失的惱人的普遍解決方案,我認(rèn)為這很俗氣/令人分心),但我最終編譯了3個(gè)必需的組件來(lái)禁用滾動(dòng)條,同時(shí)保持它可見(jiàn)[僅在Chromium(Edge)和開(kāi)發(fā)工具中的移動(dòng)仿真器中測(cè)試]:
阻止?jié)L輪滾動(dòng)
...
function App(){
const [isModalOpen, setIsModalOpen] = useState(false)
useEffect(() => {
const handleWindowWheel = (event: WheelEvent) => {
if (isModalOpen){
event.preventDefault();
}
};
window.addEventListener('wheel', handleWindowWheel, { passive: false });
return () => {
window.removeEventListener('wheel', handleWindowWheel);
};
}, [isModalOpen]);
return (
...
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
...
)
}
阻止點(diǎn)擊拖動(dòng)滾動(dòng)
...
function disableScroll() {
// Store the current X & Y scroll positions.
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
// If any scroll event is attempted on the window, change the window's
// onscroll function to always scroll back to the saved X & Y positions.
window.onscroll = function() {
window.scrollTo(scrollLeft, scrollTop);
};
}
function enableScroll() {
// Reset the window's onscroll function.
window.onscroll = function() {};
}
function App(){
const [isModalOpen, setIsModalOpen] = useState(false)
useEffect(() => {
if (isModalOpen) {
disableScroll();
} else {
enableScroll();
}
}, [isModalOpen]);
return (
...
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
...
)
}
信用
上面的代碼片段也半阻止了ScrollWheel scroll,但是它很難看:它允許你用滾輪滾動(dòng)滾動(dòng)條一個(gè)完整的ScrollWheel-click的距離,然后明顯地將滾動(dòng)條彈回到原來(lái)的位置。(這也是為什么建議另外實(shí)現(xiàn)塊滾輪滾動(dòng)的原因。)
阻止手指滾動(dòng)(移動(dòng))
...
function App(){
const [isModalOpen, setIsModalOpen] = useState(false)
...
return (
{/* Sets the 'touch-action' CSS property to 'none' on
the outermost div when the modal is open. */}
<div style={{ touchAction: isModalOpen ? 'none' : 'auto' }}>
...
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
...
</div>
)
}
組合(功能演示):
const {useState} = React;
const {useEffect} = React;
function disableScroll() {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
window.onscroll = function() {
window.scrollTo(scrollLeft, scrollTop);
};
}
function enableScroll() {
window.onscroll = function() {};
}
const ExampleComponent = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
useEffect(() => {
if (isModalOpen) {
disableScroll();
} else {
enableScroll();
}
const handleWindowWheel = (event: WheelEvent) => {
if (isModalOpen){
event.preventDefault();
}
};
window.addEventListener('wheel', handleWindowWheel, { passive: false });
return () => {
window.removeEventListener('wheel', handleWindowWheel);
};
}, [isModalOpen]);
return (
<div className={isModalOpen ? 'disable-touch-scroll' : ''}>
{isModalOpen &&
<div id="modal">
<span>You shouldn't be able to scroll now.</span>
<button
onClick={() => setIsModalOpen(false)}
>
Close Modal
</button>
</div>
}
<div>
{"hello ".repeat(1000)}
</div>
<button
id="modal-open-button"
onClick={() => setIsModalOpen(true)}
>
Open Modal
</button>
</div>
);
};
ReactDOM.createRoot(
document.getElementById("root")
).render(
<ExampleComponent/>
);
#modal {
width: 50%;
height: 50%;
position: fixed;
z-index: 999;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
background: white;
border: 1px solid black;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#modal-open-button {
position: fixed;
top: 50%;
color: white;
background-color: red;
}
.disable-touch-scroll {
touch-action: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>