在Vue2组件中未定义document.getElementById ...由于滥用手表?

时间:2019-07-14 12:43:27

标签: html vue.js vuejs2

我正在制作一个基本的聊天组件,可将消息从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'

  •   

2 个答案:

答案 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中创建了一个工作示例。