如何滚动到一个元素?

IT技术 javascript reactjs ecmascript-6
2021-01-16 05:03:05

我有一个聊天小部件,每次向上滚动时都会拉出一系列消息。我现在面临的问题是当消息加载时滑块固定在顶部。我希望它专注于前一个数组中的最后一个索引元素。我发现我可以通过传递索引来创建动态引用,但我还需要知道使用什么样的滚动函数来实现这一点

 handleScrollToElement(event) {
    const tesNode = ReactDOM.findDOMNode(this.refs.test)
    if (some_logic){
      //scroll to testNode      
    }
  }

  render() {

    return (
      <div>
        <div ref="test"></div>
      </div>)
  }
6个回答

React 16.8+,函数式组件

const ScrollDemo = () => {
   const myRef = useRef(null)

   const executeScroll = () => myRef.current.scrollIntoView()    
   // run this function from an event handler or an effect to execute scroll 

   return (
      <> 
         <div ref={myRef}>Element to scroll to</div> 
         <button onClick={executeScroll}> Click to scroll </button> 
      </>
   )
}

单击此处获取有关 StackBlits 的完整演示

React 16.3+,类组件

class ReadyToScroll extends Component {
    constructor(props) {
        super(props)
        this.myRef = React.createRef()  
    }

    render() {
        return <div ref={this.myRef}>Element to scroll to</div> 
    }  

    executeScroll = () => this.myRef.current.scrollIntoView()
    // run this method to execute scrolling. 
}

类组件 - Ref 回调

class ReadyToScroll extends Component {  
    render() {
        return <div ref={ (ref) => this.myRef=ref }>Element to scroll to</div>
    } 

    executeScroll = () => this.myRef.scrollIntoView()
    // run this method to execute scrolling. 
}

不要使用字符串引用。

字符串引用会损害性能,不可组合,并且即将消失(2018 年 8 月)。

字符串引用有一些问题,被认为是遗留的,可能会在未来的版本之一中被删除。[官方 React 文档]

资源 1资源 2

可选:平滑滚动动画

/* css */
html {
    scroll-behavior: smooth;
}

将 ref 传递给孩子

我们希望 ref 附加到一个 dom 元素,而不是一个 react 组件。因此,当将其传递给子组件时,我们无法命名 prop ref。

const MyComponent = () => {
    const myRef = useRef(null)
    return <ChildComp refProp={myRef}></ChildComp>
} 

然后将 ref 属性附加到 dom 元素。

const ChildComp = (props) => {
    return <div ref={props.refProp} />
}
事后很明显,但重要的是要提到这仅适用于原生 DOM 元素,而不仅仅是任何 React 组件。
2021-03-18 05:03:05
window.scrollTo(0, offsetTop) 是一个更好的选择,在当前浏览器中提供更好的支持
2021-03-22 05:03:05
可以确保您在示例中保持一致。我们从 myRef 开始,以 domRef 开始,以 tesNode ? 结束。这很令人困惑
2021-03-26 05:03:05
@jpunk11 我刚刚更新了我的答案。更新后的答案解释了如何滚动到子类组件中的 dom 元素。
2021-03-31 05:03:05
@SimonFranzen 看看我更新的答案 - TLDR - 类组件案例。当 scrollToMyRef 被调用时,它会滚动到你附加了 ref 的孩子。您可以将该方法传递给不同的子组件,并从那里触发它。
2021-04-02 05:03:05

这对我有用

this.anyRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' })

编辑:我想根据评论对此进行扩展。

const scrollTo = (ref) => {
  if (ref && ref.current /* + other conditions */) {
    ref.current.scrollIntoView({ behavior: 'smooth', block: 'start' })
  }
}

<div ref={scrollTo}>Item</div>
为我工作,只需注意 'start' 是 'block' 参数的默认值。
2021-03-20 05:03:05
在生命周期方法或构造函数中
2021-03-22 05:03:05
把这个放在哪里
2021-04-05 05:03:05
奇迹般有效。以上都不适合我,这应该是可以接受的答案!
2021-04-06 05:03:05
当@Ben Carp 的回答无效时,这对我有用。
2021-04-08 05:03:05

只需找到您已经确定的元素的顶部位置https://www.w3schools.com/Jsref/prop_element_offsettop.asp然后通过scrollTo方法https://www.w3schools.com/Jsref/met_win_scrollto.asp滚动到该位置

这样的事情应该工作:

handleScrollToElement(event) {
  const tesNode = ReactDOM.findDOMNode(this.refs.test)
  if (some_logic){
    window.scrollTo(0, tesNode.offsetTop);
  }
}

render() {

  return (
    <div>
      <div ref="test"></div>
    </div>)
}

更新:

因为阵营v16.3React.createRef()优选

constructor(props) {
  super(props);
  this.myRef = React.createRef();
}

handleScrollToElement(event) {
  if (<some_logic>){
    window.scrollTo(0, this.myRef.current.offsetTop);
  }
}

render() {

  return (
    <div>
      <div ref={this.myRef}></div>
    </div>)
}
根据官方文档,您应该尽量避免使用findDOMNode. 在大多数情况下,您可以将 ref 附加到 DOM 节点并完全避免使用findDOMNode
2021-03-23 05:03:05
这是更好的答案。使用ReactDOM.findDomNode()是更好的实践 - 由于 React 重新渲染组件,因此在您调用该函数时,您仅通过其 ID 获得的 div 可能不存在
2021-03-29 05:03:05
请注意,不推荐通过字符串映射使用 this.refs,请参阅:stackoverflow.com/questions/43873511/...
2021-03-30 05:03:05
注意:我必须使用this.myRef.current.scrollIntoView()而不是window.scrollTo(0, this.myRef).
2021-04-03 05:03:05

您现在可以使用useReffrom react hook API

https://reactjs.org/docs/hooks-reference.html#useref

宣言

let myRef = useRef()

零件

<div ref={myRef}>My Component</div>

利用

window.scrollTo({ behavior: 'smooth', top: myRef.current.offsetTop })
我正在尝试使用您的代码。我可以看到,通过console.log它正在执行您的window.scrollTo语句(针对我的情况进行了调整),但它没有滚动。这可能与我使用 React Bootstrap Modal 的事实有关吗?
2021-03-27 05:03:05

2019 年 7 月 - 专用钩子/函数

专用的钩子/函数可以隐藏实现细节,并为您的组件提供简单的 API。

React 16.8 + 函数式组件

const useScroll = () => {
  const elRef = useRef(null);
  const executeScroll = () => elRef.current.scrollIntoView();

  return [executeScroll, elRef];
};

在任何功能组件中使用它。

const ScrollDemo = () => {
    const [executeScroll, elRef] = useScroll()
    useEffect(executeScroll, []) // Runs after component mounts
    
    return <div ref={elRef}>Element to scroll to</div> 
}

完整演示

React 16.3 + 类组件

const utilizeScroll = () => {
  const elRef = React.createRef();
  const executeScroll = () => elRef.current.scrollIntoView();

  return { executeScroll, elRef };
};

在任何类组件中使用它。

class ScrollDemo extends Component {
  constructor(props) {
    super(props);
    this.elScroll = utilizeScroll();
  }

  componentDidMount() {
    this.elScroll.executeScroll();
  }

  render(){
    return <div ref={this.elScroll.elRef}>Element to scroll to</div> 
  }
} 

完整演示