繁体   English   中英

使用 Vue.js 滚动到 div 的底部

[英]Scroll to bottom of div with Vue.js

我有一个 Vue.js 组件,其中包含多个元素。 当调用组件中的方法时,我想自动滚动到该元素的底部。

基本上,做同样的事情 但是,我还没有找到一种方法来获取组件中的元素并修改scrollTop

我目前正在使用 Vue.js 2.0.8。

2022 简单、易读、流畅的滚动能力,而且不会伤害你的大脑……使用el.scrollIntoView()

scrollIntoView()有一些选项,您可以像scrollIntoView({behavior: 'smooth'})一样传递它来获得开箱即用的平滑滚动,并且不需要任何外部库。

这是一个小提琴

methods: {
  scrollToElement() {
    const el = this.$refs.scrollToMe;

    if (el) {
      // Use el.scrollIntoView() to instantly scroll to the element
      el.scrollIntoView({behavior: 'smooth'});
    }
  }
}

然后,如果你想在页面加载时滚动到这个元素,你可以这样调用这个方法:

mounted() {
  this.scrollToElement();
}

否则,如果您想通过单击按钮或其他操作滚动到它,您可以用相同的方式调用它:

<button @click="scrollToElement">scroll to me</button>

滚动一直有效到 IE 8。平滑滚动效果在 IE 或 Safari 中无法开箱即用。 如果需要,这里有一个可用的polyfill,正如评论中提到的@mostafaznv。

据我了解,您想要的效果是在发生某些事情时(例如:将项目添加到列表中)滚动到列表的末尾(或可滚动的div )。 如果是这样,您可以仅使用纯 JavaScript 和 VueJS 选择器滚动到容器元素的末尾(甚至是它本身的页面)。

var container = this.$el.querySelector("#container");
container.scrollTop = container.scrollHeight;

我在这个 fiddle中提供了一个工作示例。

每次将项目添加到列表时,列表都会滚动到末尾以显示新项目。

希望这对您有所帮助。

我尝试了接受的解决方案,但它对我不起作用。 我使用浏览器调试器并发现应该使用的实际高度是clientHeight您必须将其放入updated()挂钩才能使整个解决方案正常工作。

data(){
return {
  conversation: [
    {
    }
  ]
 },
mounted(){
 EventBus.$on('msg-ctr--push-msg-in-conversation', textMsg => {
  this.conversation.push(textMsg)
  // Didn't work doing scroll here
 })
},
updated(){              <=== PUT IT HERE !!
  var elem = this.$el
  elem.scrollTop = elem.clientHeight;
},
  1. 使用 DOM 元素上的ref属性进行引用
<div class="content scrollable" ref="msgContainer">
    <!-- content -->
</div>
  1. 您需要设置一个 WATCH
  data() {
    return {
      count: 5
    };
  },
  watch: {
    count: function() {
      this.$nextTick(function() {
        var container = this.$refs.msgContainer;
        container.scrollTop = container.scrollHeight + 120;
      });
    }
  }
  1. 确保您使用正确的 CSS
.scrollable {
  overflow: hidden;
  overflow-y: scroll;
  height: calc(100vh - 20px);
}

这是一个使用ref滚动到div底部的简单示例。

 /* Defined somewhere: var vueContent = new Vue({ el: '#vue-content', ... */ var messageDisplay = vueContent.$refs.messageDisplay; messageDisplay.scrollTop = messageDisplay.scrollHeight;
 <div id='vue-content'> <div ref='messageDisplay' id='messages'> <div v-for="message in messages"> {{ message }} </div> </div> </div>

请注意,通过将ref='messageDisplay'放在 HTML 中,您可以通过vueContent.$refs.messageDisplay访问该元素

如果需要支持 IE11 和(旧)Edge,可以使用:

scrollToBottom() {
    let element = document.getElementById("yourID");
    element.scrollIntoView(false);
}

如果您不需要支持 IE11,以下将起作用(更清晰的代码):

scrollToBottom() {
    let element = document.getElementById("yourID");
    element.scrollIntoView({behavior: "smooth", block: "end"});
}

尝试vue-chat-scroll

通过 npm 安装: npm install --save vue-chat-scroll

进口:

import Vue from 'vue'
import VueChatScroll from 'vue-chat-scroll'
Vue.use(VueChatScroll)

app.js之后window.Vue = require('vue').default;

然后使用它:

<ul class="messages" v-chat-scroll>
  // your message/chat code...
</ul>

对于那些没有在上面找到可行解决方案的人,我相信我有一个可行的解决方案。 我的具体用例是每当有新消息添加到数组时,我想滚动到特定 div 的底部——在我的例子中是一个聊天框。

const container = this.$el.querySelector('#messagesCardContent');
        this.$nextTick(() => {
          // DOM updated
          container.scrollTop = container.scrollHeight;
        });

我必须使用 nextTick 因为我们需要等待 dom 从数据更改中更新,然后再进行滚动!

我只是将上面的代码放在消息数组的观察器中,如下所示:

messages: {
      handler() {
        // this scrolls the messages to the bottom on loading data
        const container = this.$el.querySelector('#messagesCard');
        this.$nextTick(() => {
          // DOM updated
          container.scrollTop = container.scrollHeight;
        });
      },
      deep: true,
    }, 

在您发布的相关问题中,我们已经有一种方法可以在纯 javascript 中实现这一点,因此我们只需要获取对要滚动的 dom 节点的 js 引用。

ref属性可用于声明对 html 元素的引用,以使它们在 vue 的组件方法中可用。

或者,如果method in the component是某个 UI 事件的处理程序,并且目标与您要在空间中滚动的 div 相关,您可以简单地将事件对象连同您想要的参数一起传递,然后像这样进行滚动scroll(event.target.nextSibling)

我的应用程序有同样的需求(具有复杂的嵌套组件结构),但不幸的是我没有成功使它工作。

最后我使用了vue-scrollto效果很好!

该解决方案对我不起作用,但以下代码对我有用。 我正在处理带有message-box类的动态项目。

scrollToEnd() {
            setTimeout(() => {
                this.$el
                    .getElementsByClassName("message-box")
                    [
                        this.$el.getElementsByClassName("message-box").length -
                            1
                    ].scrollIntoView();
            }, 50);
        }

请记住将方法放在mounted()中而不是created()中,并将类message-box添加到动态项中。

setTimeout()对此工作至关重要。 您可以参考https://forum.vuejs.org/t/getelementsbyclassname-and-htmlcollection-within-a-watcher/26478了解更多信息。

这对我有用

this.$nextTick(() => {
   let scrollHeight = this.$refs.messages.scrollHeight
   window.scrollTo(0, scrollHeight)
})

没有模块的解决方案:

模板

<div class="scrollable-content" ref="conversations" />

脚本

scrollToBottom() {
  const container = this.$refs.conversations;
  container.scrollTop = container.scrollHeight;
},
scrollToBottom() {
    this.$nextTick(function () {
        let BoxEl = document.querySelector('#Box');
        if(BoxEl)
            BoxEl.scrollTop = BoxEl.scrollHeight;
    });
}

同意卢雷恩·佩雷拉

只是想添加额外的信息

watch: {
    arrayName: {
      handler() {
        const container = this.$el.querySelector("#idName");
        this.$nextTick(() => {
          container.scrollTop = container.scrollHeight;
        });
      },
      deep: true,
    },
  },

然而:

arrayName = 数组名称

idName = id 属性必须添加到您希望滚动条在 arrayName 长度增加时自动向下滚动的 div 中。

  scrollToElement() {
    const element = this.$refs.abc; // here abc is the ref of the element

    if (element) {
      el.scrollIntoView({behavior: 'smooth'});
    }
  }
}

在这里,您需要将 ref 用于要在滚动时显示的特定 div 或元素。

如果你有一张桌子,并且你想找到桌子的最后一行,那么你必须使用 -

element.lastElementChild.scrollIntoView({behaviour:'smooth'})

这并不是说如果您将元素异步添加到表中,那么您必须处理它。 您可以使用 setTimeout 对其进行测试,如果这有什么不同的话。

例如

    const element = this.$refs.abc;
    if (element) {
      setTimeout(() => {
        element.lastElementChild.scrollIntoView({behaviour:'smooth'})
      }, 1000);

    }
  }

用您自己的异步逻辑替换设置超时。

使用组合 API 和 TypeScript


我将参数scrollTop设置为scrollHeight API 中的HTMLDivElment

<template>
 <div id="container" ref="comments">
  Content ...
 </div>
</template>
<script lang="ts>
import { defineComponent, ref, Ref, watchEffect } from 'vue'

export default defineComponent({
 setup() {
  const comments: Ref<null | HTMLDivElement> = ref(null)

  watchEffect(() => {
   if(comments.value) {
    comments.value.scrollTop = comments.value.scrollHeight
   }
  })

  return {
   comments
  }
 }
})
</script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM