在 React 中处理滚动动画
Posted
技术标签:
【中文标题】在 React 中处理滚动动画【英文标题】:Handling scroll Animation in React 【发布时间】:2017-11-06 14:09:42 【问题描述】:在 React 中处理滚动位置的正确方法是什么?由于更好的用户体验,我真的很喜欢平滑滚动。由于在 React 中操作 DOM 是一种反模式,我遇到了问题:如何平滑滚动到某个位置/元素?我通常会更改元素的 scrollTop 值,但这是对 DOM 的操作,这是不允许的。
JSBIN
代码:
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 的方式实现这一点?
【问题讨论】:
请记住,操作 DOM 是一种反模式,因为 React 本质上是一个 DOM 管理器,因此它必须保持对 DOM 中发生的一切的感知;话虽如此,您始终可以使用findDOMNode
和 getBoundingClientRect
之类的东西直接观察 DOM 节点。只读就好了。
【参考方案1】:
您可以只使用 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')
编辑:由于所有浏览器 (overview of browser support) 尚不支持此方法,您可能需要使用 polyfill。
【讨论】:
这是仅用于 React Native 还是? 警告:自 2018 年 11 月起,浏览器对scrollIntoView
上平滑滚动选项的支持仅限于 Chrome 和 Firefox
是一个Javscript方法,所以不依赖React。在这里你可以看到specification and browser support。由于并非所有浏览器都支持它,因此您可能需要使用 polyfill。我使用了this polyfill,这对我来说非常有效
这似乎是最好的选择,如果你包括 polyfill。当所有浏览器都实现这一点时,您只需删除 polyfill 即可。感谢您提供此解决方案,效果很好! @sympi 你应该接受这个作为正确答案。
@bbrinx 您的 polyfill 链接指向规范页面。【参考方案2】:
window.scroll(top: 0, left: 0, behavior: 'smooth' )
为我工作。
您还需要检查browser's compability
或使用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()
)()
通过这种动态填充,除非浏览器支持平滑滚动,否则包是通过 ajax 加载的。
polyfill-modern
是一个任意的块名称,它提示 webpack 编译器将包组合在一起,以减少对服务器的请求数。
【讨论】:
如果您只想“npm install”解决问题 - npmjs.com/package/smoothscroll-polyfill【参考方案3】:最简单的方法:-
window.scrollTo(top: 0, left: 0, behavior: 'smooth' );
这个简单的 javascript 代码适用于所有浏览器。
【讨论】:
自 2021 年 7 月起,这将不适用于 Safari。请参阅其他答案,主要与 polyfill 相关【参考方案4】:已经有几个很好的包可以为你处理这个问题:
https://github.com/fisshy/react-scroll - Demo
https://www.npmjs.com/package/react-scroll-to-component 简单滚动到组件
希望这会有所帮助!
【讨论】:
@PaulCo fisshy.github.io/react-scroll-example/basic/index.html 的演示对我来说效果很好 是左上角的列表应该可以点击滚动还是只是基于视口位置的样式? 是的,顶部菜单点击正在 Chrome 中为我滚动到该页面。 在 FF 中我遇到了控制台错误:ReferenceError: event is not defined
,没关系,我会在 Chromium 中观看这个!【参考方案5】:
在 React 中有几个用于滚动到锚点的库。选择哪一种取决于您正在寻找的功能和页面的现有设置。
React Scrollable Anchor 是一个轻量级库,专门用于滚动到映射到 URL 哈希的锚点。它还根据当前关注的部分更新 URL 哈希。 [完全披露:我是这个库的作者]
在另一个答案中提到的 React Scroll 是一个功能更齐全的库,用于滚动到锚点,而不反映 URL 中的任何位置。
如果你已经在使用 React Router,你也可以连接像 React Router Hash Link Scroll 这样的东西,它也会绑定到你的 URL 哈希中。
【讨论】:
因为你是一个这样做的库的作者,并且 op 询问了 如何以反应的方式做到这一点,没有库。 (这就是我提出问题的方式,并希望得到答案)【参考方案6】:这是一个使用钩子的小型、无依赖解决方案
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')
【讨论】:
【参考方案7】:我真的很喜欢 API 部分中的react-router website,他们似乎使用了这个scrollToDoc component,这是一个将典型的 VanillaJS 平滑滚动函数非常漂亮的翻译成依赖于react-motion
的 React!
【讨论】:
以上是关于在 React 中处理滚动动画的主要内容,如果未能解决你的问题,请参考以下文章