使用 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.
这个解决方案不会伤害你的大脑,不必考虑scrollTop
或scrollHeight
,内置平滑滚动,甚至可以在 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 的底部的主要内容,如果未能解决你的问题,请参考以下文章