reactjs 在React中处理滚动动画

x8goxv8g  于 2022-11-29  发布在  React
关注(0)|答案(8)|浏览(251)

在React中处理滚动位置的 * 正确 * 方式是什么?我真的很喜欢平滑滚动,因为它有更好的UX。由于在React中操作DOM是一个反模式,我遇到了问题:如何平滑地滚动到某个位置/元素?2我通常会改变一个元素的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 方式实现这一点?

4xy9mtcn

4xy9mtcn1#

你可以只使用refs和scrollIntoView方法(使用behavior: 'smooth'可以平滑滚动),它只需要几行代码,不需要一个包。
假设这是您要滚动到的内容

<p ref={this.myRef} className="scrollToHere">[1] ...</p>

还有某种按钮

<button onClick={() => {this.scroll(this.myRef)}} className="footnote">[1]</button>

调用scroll方法

class App extends Component {
  constructor() {
    super()
    this.myRef = React.createRef();

  scroll(ref) {
    ref.current.scrollIntoView({behavior: 'smooth'})
  }
}

编辑:由于此方法尚未被所有浏览器支持(浏览器支持概述),您可能需要使用polyfill

cngwdvgl

cngwdvgl2#

window.scroll({top: 0, left: 0, behavior: 'smooth' })适合我。
您还需要检查浏览器的兼容性
或者使用polyfill
编辑:为了完整起见,这里是如何动态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编译器将包组合在一起,以便减少对服务器的请求数量。

tkclm6bt

tkclm6bt3#

最简单的方法:-

window.scrollTo({top: 0, left: 0, behavior: 'smooth' });

这段简单的JavaScript代码适用于所有浏览器。

xxls0lw8

xxls0lw84#

这里有一个使用钩子的小型、无依赖性的解决方案

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'})

nbnkbykc

nbnkbykc5#

已经有几个很好的软件包可以为您处理这个问题:
https://github.com/fisshy/react-scrollDemo
https://www.npmjs.com/package/react-scroll-to-component简单滚动到组件
希望这对你有帮助!

l3zydbqr

l3zydbqr6#

在React中有几个库可以滚动到锚点。选择哪一个取决于您正在寻找的功能和页面的现有设置。
React Scrollable Anchor是一个轻量级库,专门用于滚动到Map到URL哈希的锚点。它还根据当前关注的部分更新URL哈希。[完整披露:我是这个库的作者]
React Scroll,在另一个答案中提到,是一个功能更全面的库,用于滚动到锚点,在URL中没有任何位置的反映。
如果您已经在使用React Router,您还可以连接类似React Router Hash Link Scroll的东西,它也将绑定到您的URL哈希中。

4nkexdtk

4nkexdtk7#

我真的很喜欢API部分中的react-router website,他们似乎使用了这个scrollToDoc component,这是一个典型的VanillaJS平滑滚动函数到依赖于react-motion的React的真正甜蜜的翻译!

nxowjjhe

nxowjjhe8#

简易挂钩:

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>
        </>
    )
}

相关问题