Announcing Ionic Vue
Today I am thrilled to announce the release of Ionic Vue, a native Vue version of Ionic Framework that makes it easy to build apps for iOS, Android, and the web as a Progressive Web App. Ionic Vue has been written to take advantage of all the great new features that recently shipped in Vue 3.
Ionic Vue represents a big milestone in Ionic Framework’s development after the release of our React integration earlier in 2020. This launch is the culmination of our “Ionic for Everyone” push that was kicked off in early 2019 with the release of Ionic Framework v4. As a result, I’d like to share some context as to how we got here and where we are going next.
Click here if you just want to get started building with Ionic Vue, I won’t be offended. 😊
A bit about Ionic Framework 💁♀️
If this is your first time hearing about Ionic, Hello there! 👋
Ionic Framework is an open source UI toolkit focused on building high quality mobile apps for native iOS, native Android, and the web! From the ground up, it’s built with HTML, CSS, and JavaScript, so web developers should feel right at home building with our components. Our components allow developers to build native experiences, all while using web technology. Today, Ionic powers > 15% of all apps.
A Brief History 📖
You might recall us releasing an Ionic Vue beta back in early 2019. That version was built for Vue 2 and lacked features such as proper v-model
support. While developing Ionic Vue and Ionic React side by side, we quickly realized they had a lot in common. In fact, we found ourselves implementing similar features and fixing the same bugs multiple times.
Also around this time, the Vue team was starting to ramp up development on Vue 3, and we decided it made sense for Ionic Framework to support that version instead. We paused Ionic Vue development and shifted focus to Ionic React. With its completion, we found ourselves with all the key learnings we needed to develop Ionic Vue, and we are really happy with the way it turned out… if we may say so ourselves.
A Big Milestone 🏆
Since its launch in January 2019, we wanted Ionic Framework v4 to be known as the app framework for every web developer. To that extent, we lovingly referred to Ionic Framework v4 as “Ionic for Everyone.” This release rebuilt Ionic Framework from the ground up with Web Components. While this change took time, it ultimately allows us to support any framework without having to re-write Ionic Framework.
Today, we are committed to supporting not just Angular, but also React and Vue. In a sense, the release of Ionic Vue is an indication that our efforts have paid off. Neither the React nor the Vue integrations required any major rewrites of Ionic Framework, and the Ionic API remains remarkably similar across framework integrations.
The release of Ionic Vue demonstrates that any web developer can build performant, cross platform applications with Ionic Framework using the framework of their choice.
Getting Started 🏃♂️
Note: The first official version of Ionic Vue is v5.4.0
Getting started with Ionic Vue is a breeze. First, be sure you have the latest version of the Ionic CLI installed:
npm install -g @ionic/cli@latest
If you used the Ionic Vue beta, be sure to update your CLI as you likely were using a pre-release version.
From here, we can use the Ionic CLI to create an Ionic Vue starter application:
ionic start my-vue-app --type vue
The CLI will guide you through the setup process by first asking a few questions. Once the application has been installed, you can start the development server by running:
ionic serve
Under the hood, the ionic serve
command uses the Vue CLI to compile your app, start a dev server, and open your app in a new browser window.
From here, we 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 { defineComponent } from 'vue';
import {
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
} from '@ionic/vue';
export default defineComponent({
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 upon the Vue Router 🧭
Like with the Angular and React versions of Ionic Framework, we chose to use the official router that is provided with Vue, vue-router
. 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 router-view
component that is 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
.
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 { defineComponent } from 'vue';
import { IonPage } from '@ionic/vue';
export default defineComponent({
name: 'HomePage',
components: { IonPage },
});
</script>
Lifecycle events can be accessed by providing the appropriate event as a method:
export default defineComponent({
name: 'HomePage',
components: {
IonPage
},
methods: {
ionViewDidEnter: () => {
...
},
ionViewDidLeave: () => {
...
},
ionViewWillEnter: () => {
...
},
ionViewWillLeave: () => {
...
}
}
});
Doing Things the Vue Way 🛠
@ionic/vue
includes support for every Ionic Framework component except for virtual scroll. We are embracing the community-driven solutions for virtual scroll in Vue applications and will be providing more information on how to get started with these solutions soon! Using components in Ionic Vue 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>
import { defineComponent, ref } from 'vue';
import { IonInput } from '@ionic/vue';
export default defineComponent({
name: 'MyComponent',
components: { IonInput },
methods: {
onChange: (ev: CustomEvent) => {
...
}
},
setup() {
const inputValueRef = ref('');
return { inputValueRef };
}
});
</script>
Overlay components, such as ion-modal
, can be 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 { defineComponent } from 'vue';
import { IonButton, IonContent, IonPage, modalController } from '@ionic/vue';
import ModalExample from '@/components/Modal.vue';
export default defineComponent({
name: 'HomePage',
components: { IonButton, IonContent, IonPage },
setup() {
const openModal = async () => {
const modal = await modalController.create({
component: ModalExample,
});
await modal.present();
};
return { openModal };
},
});
</script>
Overlay components can also be used directly in your component’s template:
<template>
<ion-page>
<ion-content>
<ion-button @click="setModal(true)">Open Modal</ion-button>
<ion-modal :is-open="isOpen" @onDidDismiss="setModal(false)">
<ModalExample></ModalExample>
</ion-modal>
</ion-content>
</ion-page>
</template>
<script>
import { defineComponent, ref } from 'vue';
import { IonButton, IonContent, IonModal, IonPage } from '@ionic/vue';
import ModalExample from '@/components/Modal.vue';
export default defineComponent({
name: 'HomePage',
components: { ModalExample, IonButton, IonContent, IonModal, IonPage },
setup() {
const isOpen = ref(false);
const setModal = (state: boolean) => (isOpen.value = state);
return { isOpen, setModal };
},
});
</script>
Building your way with either TypeScript or JavaScript ✌️
We love TypeScript at Ionic, and have believed for quite some time now that it’s a great tool for building scalable apps. That said, we know how much the Vue community values simplicity – in their tooling, languages, and more. In fact, it’s likely what drew you to Vue in the first place. Start simple – then scale up as needed.
So, if you’d prefer to use JavaScript instead of TypeScript, you can. After generating an Ionic Vue app (see above), follow these steps:
- Remove TypeScript dependencies:
npm uninstall --save typescript @types/jest @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/cli-plugin-typescript
- Change all
.ts
files to.js
. In a blank Ionic Vue app, this should only berouter/index.ts
andmain.ts
. -
Remove
@vue/typescript/recommended
and@typescript-eslint/no-explicit-any
: ‘off’, from.eslintrc.js
. -
Remove
Array<RouteRecordRaw>
fromrouter/index.js
.
Truly native experiences with Vue 📱
Vue does not natively support mobile app development, but fortunately, you can pair Ionic Vue with Capacitor. Using Ionic’s official cross-platform native runtime, you can deploy your apps as progressive web apps and iOS/Android apps – all from the same codebase.
Here’s an example using two Capacitor APIs, the Camera and Filesystem. After opening the camera on the mobile device, the user can take a new photo, then save it to device storage.
const takePhoto = async () => {
const cameraPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});
const base64Data = convertPhotoToBase64(cameraPhoto);
const savedFile = await Filesystem.writeFile({
path: 'myphoto.jpg',
data: base64Data,
directory: FilesystemDirectory.Data,
});
};
Notice that there’s no mention of “web”, “iOS”, or “Android” in the code. That’s because Capacitor automatically detects the platform the app is running on, and calls the appropriate native layer code. With Core APIs like these, coupled with full access to native SDKs, Capacitor empowers you to build truly native mobile apps.
What’s Next? 🛣
For a more in-depth look at Ionic Vue, we recommend checking our Quickstart Guide. For a more hands-on experience, take a look at our Build Your First App Guide.
While the release of Ionic Vue is an important milestone for Ionic Framework, there is always more to do. We plan on releasing complete Server Side Rendering (SSR) support for Ionic Vue in the future. Keep an eye out for a blog post on how you can get started with that!
In terms of general Ionic Framework development, we have a lot of exciting things planned, so stay tuned. Also, let us know where you would like to see Ionic Framework go next by tweeting at us @ionicframework!
Thank You 💙
I want to give a huge thank you to all the community members who helped test the Ionic Vue beta and provide feedback; this project would not have been possible without your support. Special thanks to the folks over at Modus Create and specifically Michael Tintiuc for helping us get Ionic Vue to where it is today.
We are thrilled about Ionic Vue and are excited to welcome all Vue developers to the Ionic community. We are so glad you are here and cannot wait to see what you build!