Vue页面在加载时不会向下滚动

Posted

技术标签:

【中文标题】Vue页面在加载时不会向下滚动【英文标题】:Vue Page doesn't scroll down upon loading 【发布时间】:2021-01-08 11:15:45 【问题描述】:

我在尝试使页面在加载时向下滚动到最新消息时遇到了困难。当一个人发送新消息并且页面将在发送时直接向下滚动到最新消息时,我具有相同的功能。 我尝试了一些方法,例如scrollIntoView,甚至将scrollTop设置为9999。但是,当我控制台记录scrollTop时,它仍然指示它为0。在创建消息加载后调用该函数。 任何人都可以帮助我为什么它不工作?非常感谢您的帮助,谢谢。

<v-container>
  <div id="top-nav">
    <v-avatar id="avatar">
      <img src="../../public/img/icons/myavatar.png" >
    </v-avatar>
    <div id="title-grp">
      <h3 id="sofia-title">Sofia</h3>
      <div id="online-grp">
        <span id="online-circle"></span>
        <p id="online-text">Online</p>
      </div>
    </div>
  </div>
  <div id="msg-container">
    <v-row dense>
      <v-col cols="12">
        <v-card
          style="width: fit-content"
          v-for="(message,index) in messages"
          :key="index"
          :style="'margin-left': message.isRobot ? '' : 'auto'"
          :color="message.isRobot? '#F5F3FF' :'#C66BCC'" 
          id="convo-space"
        >
          <p id="timestamp" :style="'color': message.isRobot? '#808080' : '#000000'">message.timestamp</p>
          <v-card-text
            :style="'color': message.isRobot ? 'black' : 'white', 'font-size': '16px'"
          >
            message.text
          </v-card-text>

        </v-card>
        <div id="bottom-scroll" ref="last-message"></div>   
      </v-col>
    </v-row>
  </div>    

  <div id="bottom-container">
    <div class="col-text">
      <input type="text" placeholder="Type here" id="text-input" v-model="userMessage">
    </div>
    <div class="col-btn">
      <button @click="sendMessage" id="btn-color-text"> Send </button>
    </div>
  </div>
</v-container>
        

</template>

<script>

  import config from "../config.js"
  const token = config.dialogflow.clientBot;

  import  ApiAiClient  from 'api-ai-javascript';
  const client = new ApiAiClient(accessToken: token);

  import  mapGetters  from "vuex";

  import firebase from "firebase";

  export default 
    data: () => (
      messages: [],
      userMessage: "", 
    ),
    methods: 
      sendMessage()
        var timestamp = new Date().toLocaleTimeString(undefined, hour: '2-digit', minute: '2-digit');
        const usrMessage = 
          text: this.userMessage,
          isRobot: false,
          timestamp: timestamp
        ;

        this.messages.push(usrMessage);

        client.textRequest(this.userMessage).then((response) => 
          const robotMessage = 
            text: response.result.fulfillment.speech,
            isRobot: true,
            timestamp: timestamp
          ;

          firebase
          .firestore()
          .collection("users")
          .doc(firebase.auth().currentUser.uid)
          .collection("messages")
          .add(
            userMessage: usrMessage.text,
            robotMessage: robotMessage.text,
            timestamp: timestamp 
          );

          const delay = ms => new Promise(res => setTimeout(res,ms));

          const pushMsg = async () => 
            let randNum = Math.floor(Math.random() * 8000);
            await delay(randNum);
            await this.messages.push(robotMessage);
            this.scrollToEnd();
          ;

          pushMsg();
          this.scrollToEnd();
        );
          


        this.userMessage = "";
        console.log(firebase.auth().currentUser.uid);
      ,
      scrollToEnd()
        var container = this.$el.querySelector('#msg-container');
        container.scrollTop = container.scrollHeight;
        console.log(container.scrollHeight);
        console.log(container.scrollTop);
      
    ,

    created()
      var oldMessages = [];

      firebase
      .firestore()
      .collection("users")
      .doc(firebase.auth().currentUser.uid)
      .collection("messages")
      .get()
      .then( (querySnapshot) => 
        querySnapshot.forEach(function(doc)
          var snapMsg = doc.data();
          let robot = 
            text: snapMsg.robotMessage,
            timestamp: snapMsg.timestamp,
            isRobot: true
          

          let human = 
            text: snapMsg.userMessage,
            timestamp: snapMsg.timestamp,
            isRobot: false
          
          
          oldMessages.unshift(human, robot);
          );
          this.messages = oldMessages;
          );
    ,
    mounted()
      var bottomDiv = this.$el.querySelector('#bottom-scroll');
      bottomDiv.scrollIntoView();
      console.log(bottomDiv);
      console.log(bottomDiv.scrollIntoView());

      // var bottomDiv = this.$el.querySelector('#msg-container');
      // bottomDiv.scrollTop = 9999;      
      // console.log(bottomDiv.scrollTop);

      navigator.serviceWorker.addEventListener('message', (e) => 
        console.log('Push Notification received');
        console.log(e.data.firebaseMessagingData.notification.body);
        var timestamp = new Date().toLocaleTimeString(undefined, hour: '2-digit', minute: '2-digit');
        const robotMessage = 
          text: e.data.firebaseMessagingData.notification.body,
          isRobot: true,
          timestamp: timestamp
        
        firebase
        .firestore()
        .collection("users")
        .doc(firebase.auth().currentUser.uid)
        .collection("messages")
        .add(
          robotMessage: robotMessage.text,
          timestamp: robotMessage.timestamp
        );

        this.messages.push(robotMessage);
      );
    ,
    computed: 
      ...mapGetters(
        user: "user"
      )
    
  
</script> ```

【问题讨论】:

【参考方案1】:

当数据已更新而 DOM 尚未更新时,您正在尝试更新 UI。使用 nextTick 更新 Dom/Ui 时调用 scrollToEnd,每当 DOM 更新时调用 vue nextTick

例如你的代码

const pushMsg = async () => 
        let randNum = Math.floor(Math.random() * 8000);
        await delay(randNum);
        await this.messages.push(robotMessage);
        this.scrollToEnd();
      ;

应该是

 let self= this;
 const pushMsg = async () => 
        let randNum = Math.floor(Math.random() * 8000);
        await delay(randNum);
        await this.messages.push(robotMessage);
  self.$nextTick(function()
   this.scrollToEnd();
  )
        
      ;

【讨论】:

嘿伊曼纽尔,感谢您的回答。我已尝试实施您的建议,但似乎仍然无法正常工作:( 检查github.com/ogomaemmanuel/VueChatApp/blob/master/ClientApp/… 谢谢伙计。它现在似乎起作用了。我在mounted中实现了nextTick,但它没有用。因此,我看到了您将 nextTick 放置在 watch 中的代码,最后它起作用了。谢谢@emmanuel! @AhmadNurhadi 欢迎您,请投票作为答案

以上是关于Vue页面在加载时不会向下滚动的主要内容,如果未能解决你的问题,请参考以下文章

仅当用户向下滚动时才加载部分页面的简单方法?

在 React.js 中向下滚动页面时如何加载更多搜索结果?

永久缓慢地向下滚动页面,而不会占用大量 CPU 或延迟滚动

在 Python 中使用 PhantomJS 向下滚动到无限页面的底部

Selenium:在动态加载网页中滚动到页面末尾

当我向下滚动页面时,Particles.js 不会继续 - HTML