Using Vue3 VirtualScroller In Ionic Vue App

Aaron K Saunders - Apr 10 '21 - - Dev Community

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
Enter fullscreen mode Exit fullscreen mode

Next install the npm package vue3-virtual-scroller

npm install --save vue3-virtual-scroller
Enter fullscreen mode Exit fullscreen mode

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';
Enter fullscreen mode Exit fullscreen mode

Modified main.ts with the following imports

import VueVirtualScroller from 'vue3-virtual-scroller'
import 'vue3-virtual-scroller/dist/vue3-virtual-scroller.css'
Enter fullscreen mode Exit fullscreen mode

And finally added the package with the following change

const app = createApp(App)
  .use(IonicVue)
  .use(router)
  .use(VueVirtualScroller)
Enter fullscreen mode Exit fullscreen mode

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'
  };
});
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .