使用 Reactjs 获取滚动位置

Posted

技术标签:

【中文标题】使用 Reactjs 获取滚动位置【英文标题】:Get scroll position with Reactjs 【发布时间】:2019-04-09 01:44:27 【问题描述】:

我使用 reactjs,想用click 事件处理滚动。

首先,我使用componentDidMount 呈现帖子列表。

其次,通过click event在列表中的每个帖子上,它将显示帖子详细信息并滚动到顶部(因为我将帖子详细信息放在页面的顶部位置)。

第三,通过点击帖子详细信息中的"close button",它将返回以前的帖子列表,但我希望网站将滚动到点击帖子的确切位置。

我是这样使用的:

点击事件查看帖子详情:

inSingle = (post, e) => 
   this.setState(
        post: post,
        theposition: //How to get it here?
   );
   window.scrollTo(0, 0);

我想获得theposition 的状态,然后我可以精确滚动到'Close event' 所点击帖子的位置。

【问题讨论】:

你用的是什么版本的 react? @SungKim 我正在使用最新版本 【参考方案1】:

像这样:

theposition: e.y // or, e.pageY

或者,

theposition: e.clientY - e.currentTarget.getBoundingClientRect().top

【讨论】:

【参考方案2】:

您可以像在其他 js 框架或库中一样使用事件监听器。

componentDidMount() 
  window.addEventListener('scroll', this.listenToScroll)


componentWillUnmount() 
  window.removeEventListener('scroll', this.listenToScroll)


listenToScroll = () => 
  const winScroll =
    document.body.scrollTop || document.documentElement.scrollTop

  const height =
    document.documentElement.scrollHeight -
    document.documentElement.clientHeight

  const scrolled = winScroll / height

  this.setState(
    theposition: scrolled,
  )

【讨论】:

这有助于检测滚动时是否到达页面底部。谢谢。 很高兴帮助你@raksheetbhat :)【参考方案3】:

要获取当前滚动位置,您可以使用

水平滚动量window.pageXOffset

垂直滚动量window.pageYOffset

【讨论】:

【参考方案4】:

这应该可行:

this.setState(
    post: post,
    theposition: window.pageYOffset
);

【讨论】:

不好吗?我的意思是,如果你 setState,你每次都重新渲染你的组件,似乎更好地结合 useState 和 useEffect 或 useLayoutEffect【参考方案5】:

如果您需要跟踪滚动位置,您可以使用 react hooks 来执行此操作,这样就可以在需要时随时检查滚动位置:

import React,  useState, useEffect  from 'react';

...
// inside component:

const [scrollPosition, setScrollPosition] = useState(0);
const handleScroll = () => 
    const position = window.pageYOffset;
    setScrollPosition(position);
;

useEffect(() => 
    window.addEventListener('scroll', handleScroll,  passive: true );

    return () => 
        window.removeEventListener('scroll', handleScroll);
    ;
, []);

在这种情况下,useEffect 的行为类似于componentDidMount,它会在组件渲染后触发,而且在每次渲染时都会触发,正如 Jared Beach 评论道:“window.addEventListener 足够聪明,可以丢弃后续调用相同的参数”。 .确保返回清理函数,类似于您在 componentWillUnmount 中所做的。

【讨论】:

欣赏解决方案。但是,说useEffect 类似于componentDidMount 有点误导。它运行每一个渲染,而不仅仅是第一个。此代码仍然有效,因为 window.addEventListener 足够聪明,可以丢弃具有相同参数的后续调用 总是给 window.pageYOffset 0 他的useEffect的第二个参数是一个空数组,类似于componentDidMount。如果不存在,它将类似于 componentDidUpdate。【参考方案6】:

这个 repo 帮了我很多https://github.com/n8tb1t/use-scroll-position

yarn add @n8tb1t/use-scroll-position

import  useScrollPosition  from '@n8tb1t/use-scroll-position'


useScrollPosition(( prevPos, currPos ) => 
 console.log(currPos.x)
 console.log(currPos.y)
)

【讨论】:

【参考方案7】:
import React,  useLayoutEffect, useState  from 'react';

export default function useWindowPosition() 
  const [scrollPosition, setPosition] = useState(0);
  useLayoutEffect(() => 
    function updatePosition() 
      setPosition(window.pageYOffset);
    
    window.addEventListener('scroll', updatePosition);
    updatePosition();
    return () => window.removeEventListener('scroll', updatePosition);
  , []);
  return scrollPosition;

【讨论】:

【参考方案8】:

你可以使用原生的 react 事件监听器。

<div onScroll=(e) => console.log("scrolling!", e.target.scrollTop)>
    <h3>Some huge div</h3>
</div>

【讨论】:

【参考方案9】:

在MDN找到这个:

element.scrollHeight - Math.abs(element.scrollTop) === element.clientHeight

【讨论】:

【参考方案10】:

结合其他一些答案,这正是这里所需要的。只需使用此钩子即可从窗口中获取 scrollX(水平)和 scrollY(垂直)位置。它会随着用户滚动而更新。

/// in useWindowScrollPositions.js

import  useEffect, useState  from 'react'

export const useWindowScrollPositions = () => 

   const [scrollPosition, setPosition] = useState( scrollX: 0, scrollY: 0 )

   useEffect(() => 
    function updatePosition() 
        setPosition( scrollX: window.scrollX, scrollY: window.scrollY )
    

    window.addEventListener('scroll', updatePosition)
    updatePosition()

    return () => window.removeEventListener('scroll', updatePosition)
   , [])

   return scrollPosition

然后在你的函数组件中调用钩子:

/// in MyComponent.jsx

import  useWindowScrollPositions  from 'path/to/useWindowScrollPositions'

export const MyComponent = () => 
   const  scrollX, scrollY  = useWindowScrollPositions()
   
   return <div>Scroll position is (scrollX, scrollY)</div>
 

请注意,几年前在其他答案中使用的window.pageXOffsetwindow.pageYOffset 已被弃用,取而代之的是window.scrollXwindow.scrollY

【讨论】:

以上是关于使用 Reactjs 获取滚动位置的主要内容,如果未能解决你的问题,请参考以下文章

在 ReactJS 中滚动嵌套组件

使用 ReactJS 和 Skeleton Css 滚动表格

使用 Reactjs 中的按钮进行水平滚动

使用jQuery滚动到Reactjs中的部分[重复]

ReactJS:建模双向无限滚动

reactjs创建部分可滚动的表格