我正在制作一个基本的聊天组件,可将消息从Firebase加载到div中。
relevantMessages
发生更改,目标是将当前滚动位置自动滚动到div的底部
底部。我试图通过向relevantMessages
添加一个监视程序来执行此操作,该监视程序调用了'scrollToBottom'方法。
问题是:观察者“ relevantMessages”的回调错误:
“ TypeError:无法读取未定义的属性'scrollTop'”
HTML:
<template>
<div class="all">
<div class="chat-header">
...
</div>
<div class="messages-area" id="messages-area-id" ref="messagesAreaRef">
<div
v-for="(thing, index) in relevantMessages"
:key="index"
class="message-row"
>
<div class="message">
<span>{{thing.content}}</span>
<span>{{thing.timeStamp}}</span>
</div>
</div>
</div>
<div class="input-area">
...
</div>
</template>
JS:
<script>
import firebase from "firebase";
export default {
data() {
return {
relevantMessages: Object,
partnerObj: null
};
},
computed: {
...
},
props: {
...
},
mounted: function() {
this.getMessages();
this.getPartner();
},
watch: {
relevantMessages: function() {
this.scrollToBottom();
}
},
methods: {
getMessages: function() {
var that = this;
firebase
.database()
.ref("/messages/" + that.conversationUID)
.on("value", function(messages) {
var result = messages.val();
that.relevantMessages = result;
});
console.log("getting posts");
},
sendMessage: function() {
...
},
scrollToBottom: function() {
var messagesArea = this.$refs.messagesAreaRef;
// var messagesArea = document.getElementById("messages-area-id");
var currentScrollPos = messagesArea.scrollTop;
// console.log(currentScrollPos);
var totalDivHeight = messagesArea.scrollHeight;
if (currentScrollPos <= totalDivHeight - 100) {
messagesArea.scrollTop(totalDivHeight);
}
}
}
};
错误本身:
vue.runtime.esm.js?2b0e:619 [Vue警告]:监视程序“ relevantMessages”的回调错误:“ TypeError:无法读取未定义的属性'scrollTop'”
TypeError:无法读取未定义的属性'scrollTop'
答案 0 :(得分:0)
也许此时组件本身尚未安装。因此,所有$refs
都是undefined
。在mounted()
中尝试watch(Documentation)的替代语法。希望有帮助!
答案 1 :(得分:0)
您的实现存在一些问题:
relevantMessages: Object,
Object
似乎不是relevantMessages
的有效初始值。您应将其设置为一个空对象({}
)或一个空数组([]
)。
messagesArea.scrollTop(totalDivHeight);
scrollTop
不是一个函数,应该像messagesArea.scrollTop = totalDivHeight
这样使用。
您滚动到底部的实现不正确;如果currentScrollPos
位于 top 附近,它将始终小于其容器的高度。要检查它是否接近底部,您应该使用currentScrollPos >= totalDivHeight - messagesArea.clientHeight - 100
现在,即使进行了上述更改,在Vue有机会重新渲染和更新DOM之前,观察者仍会运行并执行(因此,滚动始终在其后一个节点),因此您必须调用您在"next tick"之后的scrollToBottom
:
watch: {
relevantMessages() {
this.$nextTick(this.scrollToBottom);
}
},
我在https://codesandbox.io/embed/vue-template-tqo4k的CodeSandbox中创建了一个工作示例。