在React中滚动到溢出div的底部

时间:2017-08-16 17:42:05

标签: javascript html css reactjs

我有ul max-heightoverflow-y: auto

当用户输入足够的li元素时,ul会开始滚动,但我希望其中li的最后form始终存在且可见给用户。

我尝试实现一个如下所示的scrollToBottom函数:

scrollToBottom() {
    this.formLi.scrollIntoView({ behavior: 'smooth' });
}

但这只会让ul跳转到屏幕顶部并显示li,其中的表单是唯一可见的内容。

有没有更好的方法来实现这一目标?我发现的答案往往有点旧并使用ReactDOM。谢谢!

CSS:

.prompt-box .options-holder {
    list-style: none;
    padding: 0;
    width: 95%;
    margin: 12px auto;
    max-height: 600px;
    overflow-y: auto;
}

HTML:

<ul className='options-holder'>
    {
        this.state.items.map((item, index) => (
            <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`}>
                <div className='circle' onClick={this.removeItem} />

                <p className='item-text'>{ item.text }</p>
            </li>
        ))
    }

    <li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}>
        <div className='circle form' />

        <form className='new-item-form' onSubmit={this.handleSubmit}>
            <input 
                autoFocus 
                className='new-item-input' 
                placeholder='Type something and press return...' 
                onChange={this.handleChange} 
                value={this.state.text}
                ref={(input) => (this.formInput = input)} />
        </form>
    </li> 
</ul>

8 个答案:

答案 0 :(得分:7)

使用docs库。但是,您必须明确设置import { animateScroll } from "react-scroll"; scrollToBottom() { animateScroll.scrollToBottom({ containerId: "options-holder" }); } 的ID。

scrollToBottom

您可以在setState回调上调用this.setState({ items: newItems}, this.scrollToBottom);

例如

Element

或者使用setTimeout。

或者您甚至可以从react-scroll设置li并滚动到某个( ( number_of_days_in_the_months * 86400 ) / 100 ) * uptime_percentage = uptime_in_seconds

答案 1 :(得分:6)

我有一个可以装满页面高度的容器。此容器具有显示弯曲和弯曲方向列。然后,我有一个Messages组件,它是一个ul,每条消息一个li加上一个特殊的AlwaysScrollToBottom组件作为最后一个子组件,借助{{1} },滚动到列表底部。

useEffect

CSS是

const AlwaysScrollToBottom = () => {
  const elementRef = useRef();
  useEffect(() => elementRef.current.scrollIntoView());
  return <div ref={elementRef} />;
};

const Messages = ({ items }) => (
  <ul>
    {items.map(({id, text}) => <li key={id}>{text}</li>)}
    <AlwaysScrollToBottom />
  </ul>
)

const App = () => (
  <div className="container">
    <Messages items={[...]}>
    <MessageComposer />
  </div>
)

为简洁起见,

.container { display: flex; height: 100vh; flex-direction: column; } ul { flex-grow: 1; overflow-y: auto; } 已被省略,它包含用于发送消息的表格,输入字段等。

答案 2 :(得分:4)

好像你正在建立一个类似聊天的界面。您可以尝试将<ul>div.circle-form包装在一个单独的div中,如下所示:

&#13;
&#13;
ul{
  border:1px solid red;
  height:13em;
  overflow-y:auto;
  position:relative;
}
ul li{
  border-bottom:1px solid #ddd;
  list-style:none;
  margin-left:0;
  padding:6px;
}

.wrapper{
  background:#eee;
  height:15em;
  position:relative;
}
.circle-form{
  background:#ddd;
  height:2em;
  padding:3px;
  position:absolute;
  bottom:0;
  left:0;
  right:0;
  z-index:2;
}
.circle-form input[type=text]{
  padding:8px;
  width:50%;
}
&#13;
<div class="wrapper">
   <ul id="list">
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
       <li>item</li>
    </ul>
    <div class="circle-form">
        <input type="text" name="type_here" placeholder="Enter something..." autofocus/>
    </div>
</div>
&#13;
&#13;
&#13;

<强> 修改

使用javascript滚动到列表底部

var list = document.getElementById("list");
list.scrollTop = list.offsetHeight;

答案 3 :(得分:2)

只需使用position:sticky s.t.始终显示最后一个列表项。

li:last-child {
  position:sticky;
  bottom:0;
}

Demo

Caniuse

答案 4 :(得分:1)

我有一个脚本,我已经在我的一个项目中使用滚动顶部平滑,我做了一个小的重构来滚动你的div的高度(滚动底部)我希望它有所帮助。

<强> scroll.js

import scroll from './your-path/scroll.js';
.
.
.
<ul className='options-holder'>
{
    this.state.items.map((item, index) => (
        <li key={item.id} className={`option ${index === 0 ? 'first' : ''}`} ref={el => (this.formLi = el)}>
            <div className='circle' onClick={this.removeItem} />

            <p className='item-text'>{ item.text }</p>
        </li>
    ))
}

<li key={0} className={`option form ${this.state.items.length === 0 ? 'only' : ''}`} ref={el => (this.formLi = el)}>
    <div className='circle form' />

    <form className='new-item-form' onSubmit={this.handleSubmit}>
        <input 
            autoFocus 
            className='new-item-input' 
            placeholder='Type something and press return...' 
            onChange={this.handleChange} 
            value={this.state.text}
            ref={(input) => (this.formInput = input)} />
    </form>
</li> 

你应该在组件中导入它,有2个参数(元素的ID,在这种情况下,你可以使用ref。第二个是我用来处理速度的字符串滚动。

scroll(this.state.items[this.state.items.length - 1]);

Idk如何在渲染中映射此LI,但是您应该进行验证,如果属性溢出则应该运行滚动。

你的组件有一个合理的答案是跳到第一个元素,你是第一个元素而不是最后一个元素。

可能的解决方法:

{{1}}

更新1:原始scroll.js的要点,scrolling to the top

答案 5 :(得分:1)

在渲染来自用户导入的组件数组时,我遇到了类似的问题。我最终使用componentDidUpdate()函数让我的工作。

componentDidUpdate() {
        // I was not using an li but may work to keep your div scrolled to the bottom as li's are getting pushed to the div
        const objDiv = document.getElementById('div');
        objDiv.scrollTop = objDiv.scrollHeight;
      }

答案 6 :(得分:0)

我用通用工具功能解决了这个问题,该功能可以在任何特定组件之外运行。您需要在父级(列表框,多行编辑等)和最后一个子级元素(或希望滚动到的位置)上定义引用。

export const scrollToRef = (parentRef, childRef) => {
    trace("scrollToRef:ref.current.offsetTop", childRef.current.offsetTop);
    parentRef.current.scrollTo(0, childRef.current.offsetTop)
}

我将其用作功能组件,并在我的父容器更新时将其称为效果。

答案 7 :(得分:0)

您可以使用“ react-scroll-to-bottom”模块来完成此操作。

添加新子项时自动滚动到底部。

import ScrollToBottom from 'react-scroll-to-bottom';

<ScrollToBottom className={ROOT_CSS}>
   <p>
       Nostrud nisi duis veniam ex esse laboris consectetur officia et. Velit 
       cillum est veniam culpa magna sit
  </p>
</ScrollToBottom>

链接:https://www.npmjs.com/package/react-scroll-to-bottom