Anyone else feeling déjà vu? It feels like not too long ago we were launching the Ionic Vue beta built with Vue 2. Given that the release of Vue 3 is quickly approaching, we thought this would be a perfect time to start preparing Ionic Vue for launch. Today, I am thrilled to announce the new and improved Ionic Vue beta built with Vue 3!

What is Ionic Framework? 🤔

Ionic Framework is a collection of UI components used for building high-quality, cross platform applications. These applications can be deployed natively to iOS and Android devices or to the web as a progressive web app (PWA). These components are written in HTML, CSS, and JavaScript, making it easy to build modern, high quality user interfaces that perform great everywhere.

We are excited to welcome Vue developers to the Ionic Framework community with the release of the Ionic Vue beta!

Hold up, didn’t you do a beta last year? 🤚

We sure did! At the time we released the old Ionic Vue beta, we were simultaneously developing Ionic Vue and Ionic React side by side. We quickly realized that the framework integrations for Ionic Vue and Ionic React had a lot in common. We found ourselves implementing similar features and fixing bugs multiple times.

Additionally, the Vue team was starting to ramp up development on Vue 3, and we wanted Ionic Framework to support that version.

After a while we decided to press pause on Ionic Vue to focus on Ionic React. Since then, we have taken everything we learned with Ionic React and incorporated it into Ionic Vue, and we are really happy with the way it turned out.

Getting Started 🏃‍♂️

We have updated Ionic Vue to support not only Vue 3 but the all new Vue Router. Getting started with Vue and Ionic is a breeze by installing a development version of the Ionic CLI:

npm install -g @ionic/cli@testing

ionic start my-app tabs --type vue --tag vue-beta

Using --tag allows you to download the latest beta version of an Ionic Vue starter. Once the application has been installed, you can start a development server by running:

ionic serve

Only version 0.3.1 and newer of the Ionic Vue beta are compatible with Vue 3. To continue using the Ionic Vue beta with Vue 2, version 0.0.9 should be used.

From here, we now have access to all of Ionic Framework’s components:

<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Hello Vue</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">Hello Vue</ion-title>
        </ion-toolbar>
      </ion-header>
    </ion-content>
  </ion-page>
</template>

<script>
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, } from '@ionic/vue';
export default {
  name: 'HomePage',
  components: {
    IonContent,
    IonHeader,
    IonPage,
    IonTitle,
    IonToolbar,
  },
};
</script>

To use the components, you need to import them from the @ionic/vue package and provide them to your Vue component.

Building on Vue Router 🧭

One of the big missing pieces of the old Ionic Vue beta was stack-based navigation. This new version of Ionic Vue brings the same robust stack management that is found in other versions of Ionic Framework. Like with the Angular and React versions of Ionic Framework, we chose to use the official router that is provided with Vue, vue-router. In order to handle Ionic Framework’s animations, we have extended the Router’s API through the ion-router-outlet component. This component is used in place of the typical keep-alive, router-view, and transition components that are used in Vue applications.

Using this modified router is mostly the same as the regular vue-router except with a few different imports. Lazy loading works out of the box too!

import { createRouter, createWebHistory } from '@ionic/vue-router';
import Home from '@/views/Home.vue'

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes: [
    {
      path: '/',
      redirect: '/home'
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    },
    {
      path: ‘/lazy’,
      component: () => import(‘@/views/Lazy.vue’)
    }
  ]
})

Rather than import createRouter and createWebHistory from vue-router, you need to import them from @ionic/vue-router. These imports wrap the vue-router functions of the same name, and provide a few additional details that let Ionic Framework work well within the Vue environment.

While we recommend relying on the tooling that Vue Router provides, we have added support for the router-link property on components that allow for it:

<ion-item router-link="/child-page">
  <ion-label>Click Me to Navigate</ion-label>
</ion-item>

You can also specify the direction using router-direction and a custom animation using router-animation.

In order for transitions and lifecycle events to work properly, each Ionic page must be wrapped in an ion-page component:

<template>
  <ion-page> ... </ion-page>
</template>

<script>
import { IonPage } from '@ionic/vue';
export default { 
  name: 'HomePage', 
  components: { IonPage } 
};
</script>

Lifecycle events can be accessed by providing the appropriate event as a method:

export default {
  name: 'HomePage',
  components: {
    IonPage
  },
  methods: {
    ionViewDidEnter: () => {
      ...
    },
    ionViewDidLeave: () => {
      ...
    },
    ionViewWillEnter: () => {
      ...
    },
    ionViewWillLeave: () => {
      ...
    }
  }
 }

Doing Things the Vue Way 🛠

@ionic/vue includes support for almost every Ionic Framework component. Using the components will still feel familiar, but will use Vue’s template syntax:

<template>
  <ion-input v-model="inputValueRef" @ionInput="onChange($event)"></ion-input>
  Value: { inputValueRef }
</template>

<script>
setup() {
  const inputValueRef = ref(‘’);
  return { inputValueRef };
}
</script>

Overlay components, such as ion-modal are created dynamically by importing the appropriate controller from @ionic/vue:

<template>
  <ion-page>
    <ion-content>
      <ion-button @click="openModal()">Open Modal</ion-button>
    </ion-content>
  </ion-page>
</template>
<script>
import { IonButton, IonContent, IonPage, modalController } from '@ionic/vue';
import ModalExample from '@/components/Modal.vue';
export default {
  name: 'HomePage',
  components: { IonButton, IonContent, IonPage },
  setup() {
    const openModal = async () => {
      const modal = await modalController.create({
        component: ModalExample
      });
      await modal.present();
    }

    return { openModal }
  }
}
</script>

What’s Next? 🚢

We are looking for feedback in the following areas:

  • Router Integration
  • Tabs Usage
  • Performance

While @ionic/vue is fairly stable, it is still in beta. As a result, we do not recommend using it in production environments just yet.

If you encounter any bugs, want to request a missing feature, or want to suggest an enhancement to Ionic Vue, feel free to create a new issue on GitHub. Please be sure to indicate in the issue title that you are using the new Ionic Vue beta!

We have also published completely revamped documentation with this release of Ionic Vue. The docs go into more detail for certain Ionic Vue concepts, so we recommend checking those out. These docs are also a work in progress, so feel free to report any issues you find or enhancements you would like to see.

We love how @ionic/vue turned out and hope you do too. It is a great time to be building apps with Ionic Framework, and we can’t wait to see what you create! 🚀

Acknowledgments

We want to give a big thank you to the folks over at Modus Create. They have been instrumental in helping Ionic Vue get to where it is today. More specifically, we want to thank Michael Tintiuc who has worked closely with our engineering team to get Ionic Framework working smoothly in Vue applications.

Signup for the Ionic Newsletter to get the latest news and updates!