在 React 中处理滚动位置的正确方法是什么?我真的很喜欢平滑滚动,因为它有更好的用户体验。由于在 React 中操作 DOM 是一种反模式,我遇到了问题:如何平滑滚动到某个位置/元素?我通常会更改元素的scrollTop值,但这是对DOM的操作,这是不允许的。
代码:
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component {
handleClick = e => {
for (let i = 1; i <= 100; i++) {
setTimeout(() => (this.node.scrollTop = i), i * 2);
}
};
render() {
const someArrayToMap = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
return (
<div ref={node => this.node = node} style={{overflow: 'auto', height: '100vh'}}>
<button onClick={this.handleClick}>CLICK TO SCROLL</button>
{
[...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap,
...someArrayToMap].map((e, i) => <div key={i}>some text here</div>)
}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
如何通过React方式实现这一点?
window.scroll({top: 0, left: 0, behavior: 'smooth' })
对我有用。
您还需要检查浏览器的兼容性
或者使用polyfill
编辑:为了完整起见,以下是如何使用 webpack 动态填充。
if (!('scrollBehavior' in document.documentElement.style)) {
//safari does not support smooth scroll
(async () => {
const {default: smoothScroll} = await import(
/* webpackChunkName: 'polyfill-modern' */
'smoothscroll-polyfill'
)
smoothScroll.polyfill()
})()
}
通过这个动态polyfill,包通过ajax加载,除非浏览器支持平滑滚动。
polyfill-modern
是任意块名称,它提示 webpack 编译器将包组合在一起,以减少对服务器的请求数量。
您可以只使用 refs 和
scrollIntoView
方法(使用 behavior: 'smooth'
实现平滑滚动)。只需几行代码,不需要包。
说这就是您要滚动到的内容
<p ref={this.myRef} className="scrollToHere">[1] ...</p>
还有某种按钮
<button onClick={() => {this.scroll(this.myRef)}} className="footnote">[1]</button>
调用滚动方法
class App extends Component {
constructor() {
super()
this.myRef = React.createRef();
scroll(ref) {
ref.current.scrollIntoView({behavior: 'smooth'})
}
}
最简单的方法:-
window.scrollTo({top: 0, left: 0, behavior: 'smooth' });
这个简单的 JavaScript 代码适用于所有浏览器。
这是一个使用钩子的小型、无依赖解决方案
const useSmoothScrollTo = id => {
const ref = useRef(null)
useEffect(() => {
const listener = e => {
if (ref.current && location.hash === id) {
ref.current.scrollIntoView({behavior: 'smooth'})
}
}
window.addEventListener('hashchange', listener, true)
return () => {
window.removeEventListener('hashchange', listener)
}
}, [])
return {
'data-anchor-id': id,
ref
}
}
你这样使用它:
export const FeaturesSection = () => {
const bind = useSmoothScrollTo('#features')
return (
<section {...bind} className={classes.features}>
...
</section>
)
}
然后您只需在应用程序中的其他任何地方执行
<a href="#features">Go to Features</a>
显然,与上述相同的注意事项也适用于
.scrollIntoView({behavior: 'smooth'})
已经有几个很好的软件包可以为您处理这个问题:
https://github.com/fisshy/react-scroll - 演示
https://www.npmjs.com/package/react-scroll-to-component 简单滚动到组件
希望这有帮助!
React 中有几个用于滚动到锚点的库。选择哪一个取决于您正在寻找的功能以及页面的现有设置。
React Scrollable Anchor 是一个轻量级库,专门用于滚动到映射到 URL 哈希的锚点。它还根据当前关注的部分更新 URL 哈希。 [全面披露:我是这个库的作者]
React Scroll,在另一个答案中提到,是一个功能更齐全的库,用于滚动到锚点,而不反映 URL 中的任何位置。
如果您已经在使用 React Router,您还可以连接类似 React Router Hash Link Scroll 的东西,然后它也会与您的 URL 哈希相关联。
只需将此代码添加到您的 App.CSS
html{
scroll-behavior: smooth;
}
确保使用 NavLink 并为特定部分提供 Id。
我真的很喜欢API部分的react-router网站,他们似乎使用了这个scrollToDoc组件,这是典型的VanillaJS平滑滚动功能到React的一个非常甜蜜的翻译,它依赖于
react-motion
!
简易挂钩:
function useScrollTo(): [string, () => void] {
const id = useId();
const handleScroll = useCallback(() => {
const element = document.getElementById(id);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
}, [id]);
return [id, handleScroll];
}
及用法:
function App() {
const [section2, scrollToSection2] = useScrollTo();
return (
<>
<button onClick={scrollToSection2}>Scroll</button>
<div id={section2}>Section 2</div>
</>
)
}
我可以在不使用Javascript的情况下实现这个功能。
你可以像这样使用 HTML/CSS 来做到这一点。
html,
body,
body * {
scroll-behavior: smooth;
}
a {
background: #0003;
width: 100%;
display: block;
padding: 1em 0.5em;
border: 1px solid black;
text-decoration: none;
color: black;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Smooth Scroll Test</title>
</head>
<body>
<a href="#footer" id="header">go to footer</a>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<a href="#header" id="footer">go to header</a>
</body>
</html>