我正在尝试使用Vue和Express制作聊天应用程序。
此刻,我想使带有消息的容器在发送新消息时自动滚动到底部。我尝试通过使用scrollToEnd
函数来选择div容器并将其scrollHeight
分配给scrollTop
来做到这一点:
scrollToEnd: function () {
var messages = this.$el.querySelector('#messages')
messages.scrollTop = messages.scrollHeight
}
这给出了以下错误:
TypeError:无法读取null的属性'scrollHeight'
由于某些原因,在我在其他元素上进行测试时,使用
querySelector
总是返回null。可以在下面找到该组件的完整代码。
<template>
<div id="messages">
<ul>
<li v-for="msg in messages.slice().reverse()">{{ msg.message }}</li>
</ul>
</div>
</template>
<script>
import MessageService from '@/services/MessageService'
export default {
name: 'messages',
data () {
return {
messages: []
}
},
mounted () {
this.getMessages()
this.$root.$on('newMessage', (msg) => {
this.message = msg
this.getMessages()
this.scrollToEnd()
})
},
methods: {
async getMessages () {
const response = await MessageService.fetchMessages()
this.messages = response.data.messages
},
scrollToEnd: function () {
var messages = this.$el.querySelector('#messages')
messages.scrollTop = messages.scrollHeight
}
}
}
</script>
最佳答案
this.$el
Vue实例正在管理的根DOM元素。this.$el
是#messages
div,无需从DOM中获取它。
然后,您可以简单地使用this.$el.lastElementChild.offsetTop
获取最后一条消息并滚动到其顶部,因此,如果消息很长,则不会滚动到其起点。
在这里,我对模板进行了一些简化,以使其更明确。
<template>
<ul id="messages">
<li v-for="msg in messages.slice().reverse()">{{ msg.message }}</li>
</ul>
</template>
<script>
export default {
name: 'messages',
data() {
return { messages: [] };
},
mounted() {
this.getMessages();
},
updated() {
// whenever data changes and the component re-renders, this is called.
this.$nextTick(() => this.scrollToEnd());
},
methods: {
async getMessages () {
// ...snip...
},
scrollToEnd: function () {
// scroll to the start of the last message
this.$el.scrollTop = this.$el.lastElementChild.offsetTop;
}
}
}
</script>
如果您确实想保留
<div>
容器,则可以使用ref
。<template>
<div id="messages">
<ul ref="list">
<li v-for="msg in messages.slice().reverse()">{{ msg.message }}</li>
</ul>
</div>
</template>
然后,在组件中,可以使用
this.$refs.list
引用它。ref
用于注册对元素或子元素的引用零件。该参考将在父项下注册
组件的
$refs
对象。如果用于纯DOM元素,则引用将是该元素;如果用于子组件,则
引用将是组件实例。
尽管Vue示例经常使用本机DOM API来解决问题,但是在这种情况下使用
ref
会更容易。