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

Posted

技术标签:

【中文标题】使用 Vue.js 滚动到 div 的底部【英文标题】:Scroll to bottom of div with Vue.js 【发布时间】:2017-04-05 10:26:39 【问题描述】:

我有一个 Vue 组件,其中包含多个元素。我想在调用组件中的方法时自动滚动到该元素的底部(基本上,与Scroll to bottom of div? 中的操作相同)。但是,我还没有找到在我的组件中获取元素并修改scrolTop

的方法

我目前正在使用 Vue 2.0.8

【问题讨论】:

对我来说效果很好***.com/questions/11715646/… 【参考方案1】:

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

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

我在这个小提琴中提供了一个工作示例:https://jsfiddle.net/my54bhwn

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

希望对您有所帮助。

【讨论】:

除了this.$el.querySelector,你也可以通过ref机制选择你想要的div。 如果没有解决方案,也许你应该谷歌$nextTick()。在滚动之前,您必须等待内容完全绘制。 (查看 Alpesh 的答案) 对于使用 NUXT 的每个人:您必须在页面上输入 scrollToTop: false 才能在更改路线之间工作 @GeorgeAbitbol Refs 更像是最后的手段(hack),对它们的依赖可能会导致动态组件出现问题:例如,$refs 对象不是响应式的,因此它会继续增长添加和删​​除组件。 为什么不直接使用window.scrollTo(0, document.body.scrollHeight);【参考方案2】:

2022 简单、易读且不会伤害您的大脑...使用 el.scrollIntoView()

Here is a fiddle.

这个解决方案不会伤害你的大脑,不必考虑scrollTopscrollHeight,内置平滑滚动,甚至可以在 IE 中使用。

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 中无法开箱即用。如果需要,可以在 cmets 中提到 @mostafaznv 的 polyfill available for this here。

【讨论】:

不应该是而不是。请记住,@ 是 v-on: 的简写,而 : 是 v-bind 的简写: 这会将一个元素滚动到视图中,对我来说非常有效。赞成 我不得不使用更新而不是 monted,但效果很好;) 感谢您的解决方案。你可以使用这个 polyfill github.com/stipsan/scroll-into-view-if-needed 感谢 @mostafaznv 发现这一点 - 我已经用你的 polyfill 建议更新了我的答案。【参考方案3】:

我尝试了公认的解决方案,但它对我不起作用。我使用浏览器调试器发现应该使用的实际高度是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;
,

【讨论】:

这是一个很好的解决方案,但是任何带有组件的操作都会触发更新钩子,并且每个更新元素都会滚动到底部 谢谢,我对接受的答案有同样的问题。你的回答也为我解决了。 :) 更好的方法是将它放在相关的观察者方法中,作为(或等待)$nextTick() 的回调。这将产生相同的效果,但可能需要的资源要少得多。 对于使用 NUXT 的每个人:您必须在页面上输入 scrollToTop: false 才能在更改路线之间工作【参考方案4】:
    使用 DOM 元素上的 ref 属性作为参考
<div class="content scrollable" ref="msgContainer">
    <!-- content -->
</div>
    您需要设置手表
  data() 
    return 
      count: 5
    ;
  ,
  watch: 
    count: function() 
      this.$nextTick(function() 
        var container = this.$refs.msgContainer;
        container.scrollTop = container.scrollHeight + 120;
      );
    
  
    确保使用正确的 CSS
.scrollable 
  overflow: hidden;
  overflow-y: scroll;
  height: calc(100vh - 20px);

【讨论】:

非常有用的提示。我最初使用 setTimeout 解决了它,但这显然是可靠地获得正确计时的正确解决方案。如果您不使用“nextTick”滚动可能会在渲染之前发生 nextTick 解决了我的问题。没有它是行不通的。谢谢阿尔佩什 谢谢,这里的大多数解决方案在点击时都可以正常工作,但让它在挂载上工作的唯一方法是使用“nextTick”【参考方案5】:

这是一个使用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>

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

【讨论】:

【参考方案6】:

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

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

如果你不需要支持IE11,下面的就可以了(代码更清晰):

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

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

我发现这个选项似乎工作正常,但是,div 中字符串的呈现发生在 设置滚动之后(我正在更新字符串和滚动同样的方法)。 vue更新文本后有什么办法可以改变滚动位置吗? Vue.nextTick(function()) 等待下一次更新。【参考方案8】:

试试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>

【讨论】:

【参考方案9】:

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

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

【讨论】:

【参考方案10】:

该解决方案对我不起作用,但以下代码对我有用。我正在处理 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了解更多信息。

【讨论】:

【参考方案11】:

对于那些还没有找到上述可行解决方案的人,我相信我有一个可行的解决方案。我的具体用例是,每当向数组添加新消息时,我想滚动到特定 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,
    , 

【讨论】:

【参考方案12】:

这对我有用

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

【讨论】:

【参考方案13】:

我的解决方案没有模块

模板

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

脚本

scrollToBottom() 
  const container = this.$refs.conversations;
  container.scrollTop = container.scrollHeight;
,

【讨论】:

以上是关于使用 Vue.js 滚动到 div 的底部的主要内容,如果未能解决你的问题,请参考以下文章

检测用户何时使用 jQuery 滚动到 div 的底部

使用 Javascript 更改内容后滚动到 div 的底部

无法一直滚动到 div 的底部

滚动到扩展 div 的底部

CSS 溢出未按预期工作,无法滚动到 div 底部

创建新消息/元素时如何自动滚动到div的底部