met*_*mit 172
正如Tushar所说,你可以在聊天的底部保留一个虚拟div:
render () {
return (
<div>
<div className="MessageContainer" >
<div className="MessagesList">
{this.renderMessages()}
</div>
<div style={{ float:"left", clear: "both" }}
ref={(el) => { this.messagesEnd = el; }}>
</div>
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
然后在组件更新时滚动到它(即状态在添加新消息时更新):
scrollToBottom = () => {
this.messagesEnd.scrollIntoView({ behavior: "smooth" });
}
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
Run Code Online (Sandbox Code Playgroud)
我在这里使用标准的Element.scrollIntoView方法.
Die*_*ara 34
我只是想更新匹配新React.createRef() 方法的答案,但它基本相同,只需记住current创建的ref中的属性:
class Messages extends React.Component {
messagesEndRef = React.createRef()
componentDidMount () {
this.scrollToBottom()
}
componentDidUpdate () {
this.scrollToBottom()
}
scrollToBottom = () => {
this.messagesEnd.current.scrollIntoView({ behavior: 'smooth' })
}
render () {
const { messages } = this.props
return (
<div>
{messages.map(message => <Message key={message.id} {...message} />)}
<div ref={this.messagesEndRef} />
</div>
)
}
}
Run Code Online (Sandbox Code Playgroud)
tgd*_*gdn 30
不使用 findDOMNode
class MyComponent extends Component {
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
scrollToBottom() {
this.el.scrollIntoView({ behavior: 'smooth' });
}
render() {
return <div ref={el => { this.el = el; }} />
}
}
Run Code Online (Sandbox Code Playgroud)
Aha*_*eed 17
我的 ReactJS 版本:16.12.0
对于类组件
render()函数内部的HTML 结构
render()
return(
<body>
<div ref="messageList">
<div>Message 1</div>
<div>Message 2</div>
<div>Message 3</div>
</div>
</body>
)
)
Run Code Online (Sandbox Code Playgroud)
scrollToBottom()函数将获取元素的引用。并根据scrollIntoView()功能滚动。
scrollToBottom = () => {
const { messageList } = this.refs;
messageList.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});
}
Run Code Online (Sandbox Code Playgroud)
并调用上述函数内部componentDidMount()和componentDidUpdate()
对于功能组件(钩子)
进口useRef()和useEffect()
import { useEffect, useRef } from 'react'
Run Code Online (Sandbox Code Playgroud)
在导出函数中,(与调用 a 相同useState())
const messageRef = useRef();
Run Code Online (Sandbox Code Playgroud)
假设您必须在页面加载时滚动,
useEffect(() => {
if (messageRef.current) {
messageRef.current.scrollIntoView(
{
behavior: 'smooth',
block: 'end',
inline: 'nearest'
})
}
})
Run Code Online (Sandbox Code Playgroud)
或者,如果您希望它在执行操作后触发,
useEffect(() => {
if (messageRef.current) {
messageRef.current.scrollIntoView(
{
behavior: 'smooth',
block: 'end',
inline: 'nearest'
})
}
},
[stateVariable])
Run Code Online (Sandbox Code Playgroud)
最后,到你的HTML 结构
return(
<body>
<div ref={messageRef}> // <= The only different is we are calling a variable here
<div>Message 1</div>
<div>Message 2</div>
<div>Message 3</div>
</div>
</body>
)
Run Code Online (Sandbox Code Playgroud)
有关Element.scrollIntoView()访问developer.mozilla.org 的更多解释
Callback refs 中更详细的解释请访问reactjs.org
jk2*_*k2K 15
感谢@enlitement
我们应该避免使用findDOMNode,我们可以refs用来跟踪组件
render() {
...
return (
<div>
<div
className="MessageList"
ref={(div) => {
this.messageList = div;
}}
>
{ messageListContent }
</div>
</div>
);
}
scrollToBottom() {
const scrollHeight = this.messageList.scrollHeight;
const height = this.messageList.clientHeight;
const maxScrollTop = scrollHeight - height;
this.messageList.scrollTop = maxScrollTop > 0 ? maxScrollTop : 0;
}
componentDidUpdate() {
this.scrollToBottom();
}
Run Code Online (Sandbox Code Playgroud)
参考:
Gab*_*ult 13
如果用户已经在可滚动部分的底部,react-scrollable-feed 会自动向下滚动到最新元素。否则,它会将用户留在同一位置。我认为这对聊天组件非常有用:)
我认为无论滚动条在哪里,这里的其他答案都会强制滚动。另一个问题scrollIntoView是,如果您的可滚动 div 不在视图中,它将滚动整个页面。
它可以像这样使用:
import * as React from 'react'
import ScrollableFeed from 'react-scrollable-feed'
class App extends React.Component {
render() {
const messages = ['Item 1', 'Item 2'];
return (
<ScrollableFeed>
{messages.map((message, i) => <div key={i}>{message}</div>)}
</ScrollableFeed>
);
}
}
Run Code Online (Sandbox Code Playgroud)
只要确保有一个带有特定height或max-height
免责声明:我是包裹的所有者
Kai*_*old 13
最上面的答案中的scrollIntoView(...) 方法有两个主要问题:
它在语义上是不正确的,因为如果您的父元素滚动到窗口边界之外,它会导致整个页面滚动。浏览器实际上会滚动使元素可见所需的任何内容。
在使用 useEffect() 的功能组件中,您会得到不可靠的结果,至少在 Chrome 96.0.4665.45 中是这样。useEffect() 在页面重新加载时被调用得太快,并且滚动不会发生。使用 setTimeout(..., 0) 延迟scrollIntoView可以修复页面重新加载的问题,但不能首先在新选项卡中加载,至少对我来说是这样。 耸肩
这是我一直在使用的解决方案,它很可靠并且与旧版浏览器更兼容:
function Chat() {
const chatParent = useRef<HTMLDivElement(null);
useEffect(() => {
const domNode = chatParent.current;
if (domNode) {
domNode.scrollTop = domNode.scrollHeight;
}
})
return (
<div ref={chatParent}>
...
</div>
)
}
Run Code Online (Sandbox Code Playgroud)
如果你想用 React Hooks 做到这一点,可以遵循这个方法。因为在聊天底部放置了一个虚拟 div。这里使用了 useRef Hook。
钩子 API 参考:https : //reactjs.org/docs/hooks-reference.html#useref
import React, { useEffect, useRef } from 'react';
const ChatView = ({ ...props }) => {
const el = useRef(null);
useEffect(() => {
el.current.scrollIntoView({ block: 'end', behavior: 'smooth' });
});
return (
<div>
<div className="MessageContainer" >
<div className="MessagesList">
{this.renderMessages()}
</div>
<div id={'el'} ref={el}>
</div>
</div>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
我无法获得以下任何答案,但简单的 js 对我有用:
window.scrollTo({
top: document.body.scrollHeight,
left: 0,
behavior: 'smooth'
});
Run Code Online (Sandbox Code Playgroud)
您可以使用refs来跟踪组件.
如果你知道如何设置ref一个单独的组件(最后一个),请发布!
这是我发现对我有用的东西:
class ChatContainer extends React.Component {
render() {
const {
messages
} = this.props;
var messageBubbles = messages.map((message, idx) => (
<MessageBubble
key={message.id}
message={message.body}
ref={(ref) => this['_div' + idx] = ref}
/>
));
return (
<div>
{messageBubbles}
</div>
);
}
componentDidMount() {
this.handleResize();
// Scroll to the bottom on initialization
var len = this.props.messages.length - 1;
const node = ReactDOM.findDOMNode(this['_div' + len]);
if (node) {
node.scrollIntoView();
}
}
componentDidUpdate() {
// Scroll as new elements come along
var len = this.props.messages.length - 1;
const node = ReactDOM.findDOMNode(this['_div' + len]);
if (node) {
node.scrollIntoView();
}
}
}
Run Code Online (Sandbox Code Playgroud)
引用您的消息容器.
<div ref={(el) => { this.messagesContainer = el; }}> YOUR MESSAGES </div>
Run Code Online (Sandbox Code Playgroud)找到您的消息容器并使其scrollTop属性相等scrollHeight:
scrollToBottom = () => {
const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
};
Run Code Online (Sandbox Code Playgroud)唤起以上方法componentDidMount和componentDidUpdate.
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
Run Code Online (Sandbox Code Playgroud)这是我在我的代码中使用它的方式:
export default class StoryView extends Component {
constructor(props) {
super(props);
this.scrollToBottom = this.scrollToBottom.bind(this);
}
scrollToBottom = () => {
const messagesContainer = ReactDOM.findDOMNode(this.messagesContainer);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
};
componentDidMount() {
this.scrollToBottom();
}
componentDidUpdate() {
this.scrollToBottom();
}
render() {
return (
<div>
<Grid className="storyView">
<Row>
<div className="codeView">
<Col md={8} mdOffset={2}>
<div ref={(el) => { this.messagesContainer = el; }}
className="chat">
{
this.props.messages.map(function (message, i) {
return (
<div key={i}>
<div className="bubble" >
{message.body}
</div>
</div>
);
}, this)
}
</div>
</Col>
</div>
</Row>
</Grid>
</div>
);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95967 次 |
| 最近记录: |