joe*_*now 2 javascript scroll vue.js vue-component
我正在尝试使用 Vue 和 Express 制作一个聊天应用程序。
目前,我想让包含消息的容器在发送新消息时自动滚动到底部。scrollToEnd我尝试使用一个选择 div 容器并将其分配scrollHeight给以下函数来做到这一点scrollTop:
scrollToEnd: function () {
var messages = this.$el.querySelector('#messages')
messages.scrollTop = messages.scrollHeight
}
Run Code Online (Sandbox Code Playgroud)
这会产生以下错误:
类型错误:无法读取 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>
Run Code Online (Sandbox Code Playgroud)
this.$el\n\nVue 实例正在管理的根 DOM 元素。
\n
this.$el 是div #messages,不需要从 DOM 中获取它。
然后,您可以用来this.$el.lastElementChild.offsetTop获取最后一条消息并滚动到其顶部,因此如果它很长,您就不会滚动到其起点。
在这里,我对模板进行了一些简化,以使其开门见山。
\n<template>\n <ul id="messages">\n <li v-for="msg in messages.slice().reverse()">{{ msg.message }}</li>\n </ul>\n</template>\n\n<script>\nexport default {\n name: \'messages\',\n data() {\n return { messages: [] };\n },\n mounted() {\n this.getMessages();\n },\n updated() {\n // whenever data changes and the component re-renders, this is called.\n this.$nextTick(() => this.scrollToEnd());\n },\n methods: {\n async getMessages () {\n // ...snip...\n },\n scrollToEnd: function () {\n // scroll to the start of the last message\n this.$el.scrollTop = this.$el.lastElementChild.offsetTop;\n }\n }\n}\n</script>\nRun Code Online (Sandbox Code Playgroud)\n如果您确实想保留<div>容器,可以使用ref.
<template>\n <div id="messages">\n <ul ref="list">\n <li v-for="msg in messages.slice().reverse()">{{ msg.message }}</li>\n </ul>\n </div>\n</template>\nRun Code Online (Sandbox Code Playgroud)\n然后在组件中,您可以使用 来引用它this.$refs.list。
\n\n\n
ref用于注册对元素或子组件的引用。\n 该引用将注册在父组件xe2x80x99s$refs对象下。如果在普通 DOM 元素上使用,\n引用将是该元素;如果在子组件上使用,\n引用将是组件实例。
虽然 Vue 示例通常使用本机 DOM API 来解决问题,但ref在本例中使用要容易得多。