I'm making an e-merce type menu in Vue.js, with items which are divs that contain a fair amount of functionality and images. Performance is fairly good when rendering about 200 of these items, but when more than that many are added the site begins to perform sluggishly.
What's the best way to conditionally hide or remove Vue elements from the DOM if they are outside the current scrollable view (like ScrollViews in iOS)? Are there any plugins or libraries that can help with the performance of long lists of data items in Vue.js?
Thanks!
I'm making an e-merce type menu in Vue.js, with items which are divs that contain a fair amount of functionality and images. Performance is fairly good when rendering about 200 of these items, but when more than that many are added the site begins to perform sluggishly.
What's the best way to conditionally hide or remove Vue elements from the DOM if they are outside the current scrollable view (like ScrollViews in iOS)? Are there any plugins or libraries that can help with the performance of long lists of data items in Vue.js?
Thanks!
Share Improve this question asked Mar 30, 2017 at 20:37 T PatrickT Patrick 4151 gold badge5 silver badges16 bronze badges 1- This may be helpful. I don't have a plete answer for you, though. – Roy J Commented Mar 30, 2017 at 21:01
1 Answer
Reset to default 9I've made a demo snippet using the package I mentioned in my ment.
I've made a "signal" item that acts as the watcher. When the "signal" item leaves the viewport, the "plex-stuff" is no longer rendered. I did it this way so you can see the "plex-stuff" disappear. When the "signal" scrolls back into view, the "plex-stuff" is rendered.
You could just put the watcher on the widget root element and things will only be hidden when the whole widget is out of view. You don't want to put the v-if
on the root element, though, or it will never e back once it goes away.
const containerMonitor = scrollMonitor.createContainer(document.body);
new Vue({
el: '#app',
data: {
ids: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
},
ponents: {
widget: {
template: '#widget-template',
props: ['id'],
data() {
return {
visible: true
};
},
mounted() {
const elementWatcher = containerMonitor.create(this.$el.querySelector('.signal'));
elementWatcher.enterViewport(() => {
this.visible = true;
});
elementWatcher.exitViewport(() => {
this.visible = false;
});
}
}
}
});
.widget-container {
height: 200px;
margin: 10px;
background-color: #f0f0f0;
display: flex;
flex-flow: row wrap;
}
.signal {
height: 10px;
width: 10px;
margin: 30px;
background-color: red;
border: thin solid blue;
}
.plex-stuff {
flex-basis: 100%;
padding: 15px;
}
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.2.6/vue.min.js"></script>
<script src="https://rawgit./stutrek/scrollMonitor/master/scrollMonitor.js"></script>
<template id="widget-template">
<div class="widget-container">
<div class="signal">
</div>
<div v-if="visible" class="plex-stuff">
This is widget {{id}}.
Blah blah blah.
</div>
</div>
</template>
<div id="app">
Widgets below:
<widget v-for="id in ids" :id="id"></widget>
:widgets above
</div>