Using Vue3VirtualScroller In Ionic Vue App.
Ionic has a solution, but not one specifically for VueJS. If you look up the component in the documentation
ion-virtual-scroll is not supported in Vue. We plan on integrating with existing community-driven solutions for virtual scroll in the near future. Follow our GitHub issue thread for the latest updates.
Getting Started
I started with the base list template generated from the ionic cli.
ionic start --template list --type vue
Next install the npm package vue3-virtual-scroller
npm install --save vue3-virtual-scroller
I was getting some module errors so I needed to modify the shims-vue.d.ts
file to include the following.
declare module '*.vue' {
import { defineComponent } from 'vue'
const component: ReturnType<typeof defineComponent>
export default component
}
// THIS IS NEW
declare module 'vue3-virtual-scroller';
Modified main.ts
with the following imports
import VueVirtualScroller from 'vue3-virtual-scroller'
import 'vue3-virtual-scroller/dist/vue3-virtual-scroller.css'
And finally added the package with the following change
const app = createApp(App)
.use(IonicVue)
.use(router)
.use(VueVirtualScroller)
In The Application
First i needed to create some fake data so I modified messages.ts
to generate 255 records; I also added an image to the list so we could see what impact that had on the rendering
const messages: Message[] = [...Array(255).keys()].map((x) => {
return {
id: x + 1,
fromName: "Moe Chamont-" + x,
subject: "Family Calendar - Version " + x,
date: "Last Week",
image: 'https://via.placeholder.com/150'
};
});
I needed to modify the component that renders the list item to also include the image. All of the changes were made in the template of MessageListItem.vue
<template>
<ion-item
v-if="message"
:routerLink="'/message/' + message.id"
:detail="false"
class="list-item"
>
<!-- NEW CODE -->
<div slot="start" style="margin:12px">
<ion-img :src="message.image" style="width:80px;height:80px"></ion-img>
</div>
<ion-label class="ion-text-wrap">
<h2>
{{ message.fromName }}
<span class="date">
<ion-note>{{ message.date }}</ion-note>
<ion-icon
:icon="chevronForward"
size="small"
v-if="isIos()"
></ion-icon>
</span>
</h2>
<h3>{{ message.subject }}</h3>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</ion-label>
</ion-item>
</template>
Finally to the list; in this example i am using the fixed height version of the component. There are ways to handle variable height list item, see the package documentation.
Changes made to Home.vue
<ion-content :fullscreen="true">
<ion-list>
<RecycleScroller
class="scroller"
:items="messages"
:item-size="120"
key-field="id"
v-slot="{ item }"
>
<MessageListItem
:key="item.id"
:message="item"
/>
</RecycleScroller>
</ion-list>
</ion-content>
Conclusion
See the source code here on codesandbox.io
I read that someone stated they had issues on ios device, with the code that I have implemented above, there were no visible issues. If you have a more complex list implementation it is possible you might run into issues.
See additional video content on Ionic Framework, vuejs and reactjs on my @YouTube Channel