Why Every Vue developer should Checkout Vue 3 Now
It’s barely a month since the official release of Vue.js v3.0 Watch the announcement talk by Evan You!
Vue 3 offers a lot of amazing new features and changes which improve the framework’s overall stability, speed, and maintainability, and great development experience. Prior to the official release of Vue 3, some of these amazing features were available as plugins. This article will introduce you to the new advancement in Vue, new features introduced to the framework, and what has changed.
Improvement in the autocomplete features
Before the release of Vue 3, when using Vue 2.x there was no support for the autocomplete features as Vue developers rely heavily on external plugins such as IntelliSense provided by code editors. With full support for typescript in vue3, the autocomplete feature is greatly improved without depending on external plugins.
Composition API
Composition API which is one of the core new feature in Vue 3 was launched as a plugin a few months back, which made it possible to experiment with some Vue 3 feature in Vue 2.x while anticipating the official release of Vue 3. In Vue 3, it’s built into the package and can be used out of the box without any additional setup.
There are two main advantages to using the Composition API:
- Better organization
- Sharing/reusing the code
Vue 3 still supports the Options API used in Vue 2, which makes it very flexible.
<!-- MyBook.vue -->
<template>
<div>{{ readersNumber }} {{ book.title }}</div>
</template>
<script>
import { ref, reactive } from 'vue'
export default {
setup() {
const readersNumber = ref(0)
const book = reactive({ title: 'Vue 3 Guide' })
// expose to template
return {
readersNumber,
book
}
}
}
</script>
Exposed APIs
The exposed APIs offers a way of transforming Vue into a more versatile framework, where it can be used anywhere. This make is possible to use Vue reactivity in a React application without the need to render a Vue application inside the React application. In vue3, it is now possible to render all the Vue APIs exposed to usage within files outside the scope of application of Vue.
Vue Hooks
The major setback with mixins is that they cannot consume or use state from another mixin, which makes chaining of encapsulated logic difficult to achieve. Vue 3 provides the hooks API as a solution to the mixins limitations. Just like the popular react hooks, Vue hooks are functions which offers a cleaner and more flexible way to define and share reusable logic between components.
The code snippet below is a valid usage of Vue hooks that I implemented in one of my side projects:
import { useState, useActions, useRouter, useData, useMounted, useEffect, useComputed, useUpdated } from '@u3u/vue-hooks';
import types from '../types';
import NewsItem from '../components/NewsItem.vue';
export default {
components: {
NewsItem,
},
setup() {
const { route } = useRouter();
const { loading, currentNewsItem } = useState(['loading', 'currentNewsItem']);
const { GET_NEWS_ITEM } = useActions([types.GET_NEWS_ITEM]);
onCreated(() => {
GET_NEWS_ITEM(route.value.params.id);
});
return {
loading,
currentNewsItem,
};
},
};
Fragments API
To display more than one element or component on the page using Vue 2, we needed to have a wrapper element, encapsulating the elements that will be rendered so we can render multiple elements or components on the page. A typical example is the code snippet below:
<template>
<div>
<h1> This is the heading tag </h1>
<P>This is the paragraph tag</p>
<Cart/>
</div>
</template>
Vue3 offers the new Fragments API, which handles the multiple root elements, making it possible to declare any number of root elements on the single-file components without the need for special plugins. This helps to maintain a cleaner final code for the user. Which makes the code snippet below valid.
<template>
<h1> This is the heading tag </h1>
<P>This is the paragraph tag</p>
<Cart/>
</template>
Suspense
In Vue 2, when loading asynchronous data from the server which usually take some time, we would likely write some logic to display a loader while waiting for the data and when the data is available we then display it. Vue 3 offers the Suspense component which will manage this process, with a default view once the data is loading, and a fallback view when the data is being loaded all without the need for custom code.
<template>
<Suspense>
<template #default>
<div v-for="post in posts" :key="item.id">
<article>
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</article>
</div>
</template>
<template #fallback>
<loading-component>
</template>
</Suspense>
</template>
<script>
import axios from 'axios'
export default {
async setup() {
let posts = await axios
.get('https://jsonplaceholder.typicode.com/posts')
.then(response => {
return response.data
})
return {
posts
}
}
}
</script>
The new Vue composition API will understand the current state of your component, so it will be able to differentiate if the component is loading or if it’s ready to be displayed.
Portal
A Portal component, also known as a Teleport component is a component that can make an element go from one component to another. It has a lot of applications, including dialogs, custom menus, alerts, badges, and many other customs UIs that need to appear in various places within an application. In Vue 2 we used a third-party plugin called portal-vue to implement the portal component. In Vue 3, the portal component is built-in and it is very easy to use.
<template>
<page>
<Teleport to="#widget-box">
<div class="widget">
hello
</div>
</Teleport>
</page>
</template>
In vue3, any code enclosed within the Teleport tag will be ready to be teleported to any component within the application.
//recieving component
<template>
<div id="widget-box"/>
</template>
What has changed in vue 3
No more global Vue Instance
In Vue 2, we were accustomed to importing Vue, and prior to mounting the application, use the global Vue instance to add the plugins, filters, components, router, and store. This was a good technique where we could add anything to the Vue instance without needing to attach anything to the mounted application directly. It worked like this:
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
Vue.use(Vuex)
//create a vuex instance
const store = new Vuex.store({})
new Vue ({
store,
render: (h) => h(App)
}).$mount('#App')
Now, in Vue 3, this is no longer possible. We need to attach every component, plugin, store, and router to the mounted instance directly:
import {createApp} from 'vue'
import {createStore} from 'vuex'
import App from './app.vue'
const store = createStore({})
createApp(App)
.use(store)
.mount('#App')
Applying this method, we can create different Vue applications in the same global application, without the plugins, store, or router of the applications messing with one another.
No More Filters
The Vue filters API which is used in Vue 2 is no longer available. The Vue filter has been removed from the API. This change was made to simplify the render process and make it faster. All filters are just functions that receive a string and return a string.
Now, in Vue 3, to implement filters, we just need to pass a function to manipulate the string as follows:
{{filterFunction(textToBefiltered)}}
No more Event bus API
In Vue 2, we were able to use the power of the global Vue object to create a new Vue instance, and use this instance as an event bus that could transport messages between components and functions without any hassle.
// eventBus.js
const eventBus = new Vue()
export default eventBus
// ChildComponent.vue
import eventBus from './eventBus'
export default {
mounted() {
// adding eventHub listener
eventBus.$on('custom-event', () => {
console.log('Custom event triggered!')
})
},
beforeDestroy() {
// removing eventHub listener
eventBus.$off('custom-event')
}
}
// ParentComponent.vue
import eventBus from './eventBus'
export default {
methods: {
callGlobalCustomEvent() {
eventBus.$emit('custom-event') // if ChildComponent is mounted, we will have a message 'Custom event triggered!' in the console
}
}
}
In Vue 3, the $on
, $off
and $once
instance methods are completely removed while the $emit
method is still a part of the existing API as it’s used to trigger event handlers declaratively attached by a parent component. Since the application instances no longer implement the event emitter interface, to use an event bus strategy now, the Vue 3 official docs recommends using a third-party plugin or framework such as mitt or tiny-emitter.
No More Inline-template feature
In 2.x, Vue provided the inline-template
attribute on child components to use its inner content as its template instead of treating it as distributed.
syntax:
<my-component inline-template>
<div>
<p>These are compiled as the component's own template.</p>
<p>Not parent's transclusion content.</p>
</div>
</my-component>
This feature is no longer supported in vue 3.
Conclusion
We’ve reached the end of the article though Vue 3 has many more features that are not introduced in this article: multiple binding, emits component option, the createRenderer
API, SFC State-driven CSS Variables, and lots more. To explore all the new features in Vue 3 you can check out the Vue 3 official docs.
With Vue 3 being officially released by the community, there is no need for the experiment as we are now set to explore more new features in Vue 3 that are here to stay as there will be no further major break changes any time soon.