In my ponent, I got a messages array.
data: function () {
return {
messages: [],
first_load: false
...
}
This messages array get initially populated with an Ajax call after the creation of my ponent. After the data es from the server I just push it into my messages variable, it paints all messages in the UI amazingly but after it gets pushed I try to scroll bottom my UI so the user watches only the latest content.
data.body.data.messages.map((message) => {
this.messages.push(message)
}
this.scroll_bottom()
I noticed that performing a simple javascript scroll bottom line just after pushing my data won't work as the UI gets refreshed asynchronously (When i .push to my array it won't execute next line before syncing the UI), so I ended up adding a timeout and then scrolling bottom, but this is super shameful I think.
My hack:
watch: {
messages:{
handler: function (val, oldVal) {
if (!this.first_load) {
this.first_load = true
setTimeout(() => {
this.scroll_bottom()
}, 1000);
}
},
deep: true
}
}
Any ideas on how to leverage this? Thanks!
In my ponent, I got a messages array.
data: function () {
return {
messages: [],
first_load: false
...
}
This messages array get initially populated with an Ajax call after the creation of my ponent. After the data es from the server I just push it into my messages variable, it paints all messages in the UI amazingly but after it gets pushed I try to scroll bottom my UI so the user watches only the latest content.
data.body.data.messages.map((message) => {
this.messages.push(message)
}
this.scroll_bottom()
I noticed that performing a simple javascript scroll bottom line just after pushing my data won't work as the UI gets refreshed asynchronously (When i .push to my array it won't execute next line before syncing the UI), so I ended up adding a timeout and then scrolling bottom, but this is super shameful I think.
My hack:
watch: {
messages:{
handler: function (val, oldVal) {
if (!this.first_load) {
this.first_load = true
setTimeout(() => {
this.scroll_bottom()
}, 1000);
}
},
deep: true
}
}
Any ideas on how to leverage this? Thanks!
Share Improve this question edited Aug 15, 2018 at 4:19 Sumithran 6,5657 gold badges43 silver badges58 bronze badges asked Aug 15, 2018 at 3:52 damuz91damuz91 1,7382 gold badges27 silver badges43 bronze badges 6- 1 I don't think using a timeout is that bad. You can clear the existing timeout and create a new one when the new data es. Also you can use a debounce function to avoid rapid timeout creation. – nipunasudha Commented Aug 15, 2018 at 4:04
- 1 Take a look at Vue life-cycle hooks vuejs/v2/guide/instance.html you can use 'beforeUpdate' & 'updated' hooks for timing your scrolling. – nipunasudha Commented Aug 15, 2018 at 4:09
- 1 have you tried nextTick ? – Jacob Goh Commented Aug 15, 2018 at 4:16
- 1 Is this what you're looking for? stackoverflow./q/40730116/2813263 – Domino Commented Aug 15, 2018 at 4:22
- @nipunasudha Thanks for your ment, actually is quite a good thought. I just read the 'updated' method and that is what in theory im looking for. I just tried and it works good, except that for some reason i am doing a lot of changes to my data so it has some problems, but again in theory this is the answer, if you want go ahead and post it. – damuz91 Commented Aug 15, 2018 at 4:30
4 Answers
Reset to default 6You can use updated
life-cycle hook to do something after a DOM update. Take a look at the official documentation.
updated: function () {
//scroll down logic here
}
If your updated
logic is being called rapidly, you can always use a suitable denouncing method to slow down.
I think that watch is the right approach to that, but try using Vue.nextTick
or this.$nextTick
(to iterate just current ponent update cycle) instead of timeout:
watch: {
messages: function (val, oldVal) {
// DOM not updated yet
this.$nextTick(function () {
// DOM updated
this.first_load = true;
this.scroll_bottom();
});
}
}
If your scrollable div's id is cont
use the below method to scroll.
scroll() {
document.getElementById('cont').scrollTop = document.getElementById('cont').scrollHeight;
}
And you have to call this inside updated
hook.
updated() {
this.scroll();
}
Use v-chat-scroll in div before v-for