在做业务开发时,经常会遇到这样的需求:某某某购买了该商品,某某某抽奖获得了什么,这类消息用来吸引用户。通常需要一个滚动框来展示所有消息,且每次的新消息都会展示在滚框的顶部,但同时这个消息滚动框还是可以拖动鼠标浏览的。那么问题来了,当用户拖动鼠标正在浏览某一条消息时,突然新来一条消息就把用户正在看的消息给挤下去了,这种感觉是不是特别不爽?
解决思路如下:在新消息来了更新页面前,获取当前页面的高度A,更新完成后,用新的页面高度B减去之前的页面高度A得出值C,C的值即为滚动条因为新增了消息自动滚动了多少,然后在更新完成后的页面上获取scrollTop的值,将scrollTop的值再加上一个C的值。此时新消息来了,就可以保证我们当前浏览的消息相对整个滚动框仍然保持以前的位置。
其实很简单,但是讲起来有点绕,不知道我有没有说清楚,没有听明白的放学别走来找我。
以下是代码实现,方便大家抄作业。
代码语言:javascript复制import React, { PureComponent } from "react";
export default class SnapshotSample extends PureComponent {
state = {
messages: []
};
// 添加消息的方法
handleNewMessage() {
this.setState((prev) => ({
messages: [`msg ${prev.messages.length}`, ...prev.messages]
}));
}
componentDidMount() {
// 初始化10条消息
for (let i = 0; i < 10; i ) {
this.handleNewMessage();
}
// 每隔一秒来增加一条消息,最多200条消息
this.interval = window.setInterval(() => {
if (this.state.messages.length > 200) {
window.clearInterval(this.interval);
return;
}
this.handleNewMessage();
}, 1000);
}
// 卸载时清除定时器
componentWillUnmount() {
window.clearInterval(this.interval);
}
// 更新前获取当前的滚动高度
getSnapshotBeforeUpdate() {
return this.rootNode.scrollHeight;
}
// 将滚动的高度重新计算赋值
componentDidUpdate(prevProps, prevState, prevScrollHeight) {
const scrollTop = this.rootNode.scrollTop;
if (scrollTop < 5) {
return;
}
// 将滚动高度加上一个变化后的页面高度
this.rootNode.scrollTop = scrollTop (this.rootNode.scrollHeight - prevScrollHeight);
}
render() {
return (
<div
style={{
overflow: "auto",
height: "100px",
widows: "300px",
border: "1px solid #eee",
padding: "20px"
}}
// 将当前引用赋值给rootNode
ref={(node) => (this.rootNode = node)}
>
{this.state.messages.map((msg) => (
<div>{msg}</div>
))}
</div>
);
}
}
下课,撒优那拉。。。