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>