Vue JS 3 — The Practical Guide

Learn about most of the new features introduced in Vue JS 3 practical way!

Filip Jerga
codeburst

--

Useful Links

See free Vue 3 Course(9 hours) on https://academy.eincode.com

Github repository with starting project: https://github.com/Jerga99/vue-3-updates

We are going to cover :

  1. Global Api
  2. Composition
  3. Data option
  4. Root nodes
  5. Filters
  6. Suspense
  7. Reactivity
  8. v-models
  9. Teleport
  10. vue-router

Global API

Let’s start at the entry point of our application, the main.js file. In Vue 2 you were used to mounting Vue component like this:

In Vue 3, mounting looks like this:

Why this change? Well, if you were to create multiple Vue instances in the old version, then all application instances would share the same global configuration.

// this affects both root instances
Vue.mixin({
/* ... */
})
// this affects both root instances
Vue.directive('...', {
...
})
const app1 = new Vue({ el: '#app-1' })
const app2 = new Vue({ el: '#app-2' })

That’s not the case for Vue 3. Now you can create multiple instances each with a separate configuration.

Composition API

Inspired by React, Vue 3 is introducing composition API |“hook” functions. Vue components themself are very flexible and re-usable. With the use of a new API you can go one step further. Composition API can be very beneficial in larger applications. I will illustrate it with a simple example.

The first traditional way, a simple component that fetches and displays some data:

You can check the whole code here: Github

Let’s use composition API now, first check the code then the explanation.

Here you can see a very simple composition function responsible for fetching resources data. Composition functions usually start with the “use” keyword so developers will know it’s not just an ordinary function.

  1. “ref” will create a reactive object. If you want to get a raw value from the ref, you need to access it under the “value” property. See the following example:

That’s why I have created a resource array as a ref. If an item from the array gets added or removed we want to reflect these changes in our application.

This image from Vue Docs is worth thousand of words, when using “ref” you are passing by reference.

2. getResources will just fetch the data and assign it to resources

3. onMounted lifecycle function will be called when a component will be added to the DOM.

4. computed properties are evaluated when their dependencies(resources or resourceCount) will change

5. In the last step we will return data/functions we want to expose to a component that will use useResources hook function.

Now is the time to hook-in the composition function.

As you can see here I am calling useResources in the new “setup” function. Whatever returned in the setup will get into your component “this” context.

That’s why we can access all computed properties and resources data as before. Now they are provided with the return of useResources function.

The new setup component option is executed before the component is created, once the props are resolved, and serves as the entry point for composition API's.

Because the component instance is not yet created when setup is executed, there is no this inside a setup option.

Isn’t that amazing? I have just separated fetching of data into its own hook function and we can go even further.

Code: Github

Let’s create now search functionality.

Let’s break down useSearch.

  1. searchQuery contains an empty string value, ref is used so computed property searchedResources can react to changes of searchQuery string
  2. setSearchQuery is a simple function that assigns a searched value to searchQuery
  3. searchedResources is executed whenever the value of searchQuery or resources will change
  4. searchedResources responsibility is filtering resources. Every resource contains a title, if searchedQuery string is included in the resource title, then the resource is added to searchedResources array.
  5. Both setSearchQuery and searchedResourced are returned from the function.
  6. useSearchResources is executed from inside of useResources, values of setSearchQuery and searchedResources are taken and returned so they can be used in the component.

Now you could see how easy is to plug-in hook function without polluting component code. The only thing we need to do now is to implement input to get a search value and assign it to searchedQuery.

And that’s it! Now, whenever setSearchQuery is executed and the value of searchQuery is changed then the searchedResources are re-executed and filtered out.

Watch the full free course on https://academy.eincode.com

Code: Github

That’s the new composition API, now let’s take a look at other features.

Data Option

In Vue 2 you could define a data option with either an object or a function. In Vue 3 it will be possible only with a function. This way it gets standardized.

Filters removed

There is no longer possible to write “pipes” into templates.

<h1>{{title | capitalized }} </h1>

Such an expression is not a valid Javascript and it requires additional implementation cost on Vue side. The following expression is very easily transformed into a computed property or a function.

computed: {
capitalizedTitle() {
return title[0].toUpperCase + title.slice(1);
}
}

Multiple root nodes

In Vue 2 you had to have always one root node wrapping the rest of the other nodes.

<template>
<div>
<h1>...</h1>
<div class="container">...</div>
...
</div>
</template>

in Vue 3 that’s not the case.

<template>
<h1>...</h1>
<div class="container">...</div>
...
</template>

Suspense

Suspense is a special Vue component used for resolving components depending on asynchronous data.

First, generic example:

<Suspense>
<template #default>
<AsyncComponent>
</template>
<template #fallback>
Loading Data...
</template>
</Suspense>

With a new composition API, setup can be set as an async function. Suspense is displaying a fallback template until the setup is resolved.

Let’s see it as a practical example:

Then in the wrapper component:

Code: Github

Reactivity

Reactivity in Vue 3 has been updated rapidly. There is no need to use Vue.set or Vue.delete any longer. To achieve reactivity you can simply use native functions to manipulate arrays and objects.

// in composition API
const resources = ref([])
const addResource = newResource => resources.value.unshift(newResource)const removeResource = atIndex => resources.value.splice(atIndex ,1)const reactiveUser = ref({name: 'Filip'})
const changeName = () => reactiveUser.value.name = 'John'

In the classical component:

<script>
export default {
data() {
return {
resources: [1,2,3],
person: { name: 'Filip' }
}
}
methods: {
addResource(newResource) {
this.resources.unshift(newResource)
},
removeResource(atIndex) {
this.resources.splice(atIndex ,1)
},
changeName(newResource) {
this.person.name = 'John'
}
}
}
</script>

As you can see here to add an item we can use array function push/unshift

To remove an item use splice

To access and change an item property use dot notation

All of the changes will be reactive.

Code: Github

Multiple v-models

Now you are able to use multiple v-models on a custom component:

<ChildComponent v-model:prop1="prop1" v-model:prop2="prop2"/>

is shorthand for:

<ChildComponent
:prop1="prop1"
@update:prop1="prop1 = $event"
:prop2="prop2"
@update:prop2="prop2 = $event"
/>

Now in the specific example:

and in the form component:

We are handling input changes and emitting the events to update the values in the parent component. Don’t forget to emit an event in the format: “update:prop1” because <ChildComponent v-model:prop1="prop1" />is transformed to <ChildComponent v-model:prop1="prop1" @update:prop1="prop1 = $event" />In the previous example, you could see that even handlers update:title, update:type… are automatically provided.

Code: Github

Teleport

Provides the way how to render parts of the template outside of the current context.

To “teleport” the content we need to use the teleport component and wrap the content inside.

<teleport to="#teleportContent">
<div class="teleport-body">I am Teleported!</div>
</teleport>

this content will be “teleported” into the node with an id of “teleportContent

<div id="teleportContent"></div>

the only condition is that a node where we are teleporting to exists before content wrapped in the teleport is defined.

we can target id, data, class

<!-- ok -->
<teleport to="#some-id" />
<teleport to=".some-class" />
<teleport to="[data-teleport]" />

<!-- Wrong -->
<teleport to="h1" />
<teleport to="some-string" />

Vue Router

Same as Vue also Vue router has been updated. Let’s see the main changes:

In Vue 2:

Then in main.js:

import router from './router'; 
new Vue({render: h => h(App),
router,
components: { App }})
.$mount('#app')

In Vue 3:

import router from './router'const app = createApp(App)
app.use(router)
app.mount('#app')

Code: Github

Conclusion

We have just covered some of the main Vue 3 features. To see the full list of updates visit official Vue documentation.

To watch the full free Vue 3 course covering this and other features visit my academy page: https://academy.eincode.com

Best of luck!

Filip

--

--