相关文章推荐
玩滑板的冲锋衣  ·  javascript - ...·  1 年前    · 
慷慨大方的苦瓜  ·  用户对问题“Java ...·  1 年前    · 
精彩文章免费看

React 滚动盒子:内容滚动到最底部

参考原文: react scroll to bottom

通常,设置滚动高度可以通过设置元素的 scrollTop 属性,具体参见 Element.scrollTop - Web APIs | MDN (mozilla.org) ,使内容滚动到最底部可以将 scrollTop 设置成该元素的 scrollHeight 值。

1. 原生 HTML 中使用 JS 直接修改

在原生 HTML 中可以直接简单地获取到元素的 DOM 对象,以此直接修改元素的 scrollTop 属性。

<style>
  #scrollDiv {
    overflow: auto;
    height: 200px;
    width: 500px;
    border: 1px solid #999;
</style>
<div id="example">
  <div id="scrollDiv"></div>
  <input type="button" value="插入一行" onclick="add()">
  <span class="notice">请点击“插入一行”按钮,插入最新信息,当出现滚动条时,滚动条将自动保持在底部。</span>
<script type="text/javascript">
  const $div = document.getElementById('scrollDiv');
  function add() {
    const now = new Date();
    $div.innerHTML = $div.innerHTML + 'time ' + now + '<br />';
    $div.scrollTop = $div.scrollHeight;
  // 提前准备好足够撑满盒子的内容
  for (let i = 0; i < 20; ++i) {
    add();
</script>

2. React 中使用 Ref 获取元素对象并修改

在 React 中,修改元素的样式并没有那么容易,因为原生元素的对象属性是只读的。所以可以使用 Ref 获取元素,然后使用 scrollIntoView 轻松设置。具体实现方法在如下代码段的注释里。

可以参阅:StackOverflow中相关问题

// As Tushar mentioned, you can keep a dummy div at the bottom of your chat:
// 可以预留一个空 div 在聊天消息的盒子底部
render () {
  return (
      <div className="MessageContainer" >
        <div className="MessagesList">
          {this.renderMessages()}
        <div style={{ float:"left", clear: "both" }}
             ref={(el) => { this.messagesEnd = el; }}>
// and then scroll to it whenever your component is updated (i.e. state updated as new messages are added):
// 在组件更新时,滚动到该空 div 的位置
scrollToBottom = () => {
  this.messagesEnd.scrollIntoView({ behavior: "auto" });
componentDidMount() {
  this.scrollToBottom();
componentDidUpdate() {
  this.scrollToBottom();

如果你觉得滚动过程有延迟或卡顿,可能是因为你的组件太大。每次状态改变都会出发组件更新,造成了性能问题。可以考虑拆分组件。

3. React Hooks 语法使用 useRef

函数组件使用 React Hooks 时,可以使用 useRef 的钩子函数获取到元素 ref 对象。参考官方文档 Hooks API Reference – React (reactjs.org)

export default function ChatHistories() {
  const messagesEnd = useRef<HTMLDivElement>(null);
  const scrollToBottom = () => {
    if (messagesEnd && messagesEnd.current) {
      messagesEnd.current.scrollIntoView({ behavior: 'smooth' });
  useEffect(() => {
    scrollToBottom();
  }, []);
  return (
      <ul>{renderMessage()}</ul>
      <div style={{ clear: 'both', height: '1px', width: '100%' }} ref={messagesEnd}></div>