VueT Dark_870x220

The next version of Vue brings a lot of improvements over its predecessor. It will be faster, smaller and offer new features. In this article we go through what Vue 3 will offer.

At the time of writing this article, Vue 3 is in beta, and the stable version is supposed to be released in the second half of 2020. The next version introduces new features and improvements over Vue 2. The goals for Vue 3 were to make it faster, smaller, more maintainable and easier to utilize for targeting different platforms than just web.

New Reactivity Implementation Based on Proxies

Vue’s internal implementation has been rewritten to utilize new language features which were introduced in ES2015. The next version of Vue will use proxies for its reactivity system, instead of Object.defineProperty. This change will eliminate caveats, which are currently present in the second version of the framework. For instance, Vue is not able to detect property addition and deletion.

const vm = new Vue({
	data: {
		petName: 'Roger'
	}
})

// vm.petName is reactive

vm.petAge = 2
// vm.petAge is not reactive

Likewise, updating items that are nested in an array also will not be detected.

const vm = new Vue({
	data: {
		myPets: ['dog', 'fish', 'cat']
	}
})

// Both are not reactive
vm.myPets[2] = 'rat'
vm.items.length = 5

To solve these problems, Vue provides $set and $delete methods. With the introduction of proxies, these methods will not be needed anymore. Proxies are now supported in all major browsers; unfortunately, there is no way to polyfill them for older browsers like Internet Explorer. Therefore, Vue 3 will offer two versions, one with proxy-based reactivity, and one based on old reactivity implementation. This of course means that the caveats mentioned will still be present, but you can use Vue 3, even if you have to support older browsers.

Performance Improvements and VirtualDOM Rewrite

Vue 3 will be much faster and smaller than its predecessor. A compressed and minified file for Vue@2.6.10 weighs around 20kb, while Vue 3 is estimated to be half the size. This is a great improvement in size and will improve load time. The less code, the better after all.

What’s more, the Vue team has made great improvements to the virtualDOM implementation which was rewritten from the ground up and provides up to 100% faster mounting and patching. The image below shows performance comparison between versions 2.5 and 3. The new version is twice as fast, and uses only half the memory.

Performance Comparison Vue 2.5 vs. Vue 3 

Furthermore, with new virtualDOM implementation, the runtime will receive more hints about how to deal with code and take fast paths whenever possible. The compiler will also create better optimized code and hoist static nodes, to speed up and avoid unnecessary rendering.

Fast paths

Other improvements include optimized slots generation, static props hoisting, and inline handler hoisting. You can read more about it in Evan’s presentation here.

TypeScript

Vue core team decided to move from Flow to TypeScript for development of Vue 3. Thanks to that, developers who use TypeScript for creating their application will have better type hints, and even if they don’t use TypeScript, some code editors like VS Code will also provide more information during development. Besides that, it will also be easier to use TypeScript in Vue 3. In Vue 2, most developers use the vue-class-component library, but thanks to the Composition API, Vue will be more TypeScript-friendly.

Composition API

Composition API is a new way of writing stateful logic in Vue components. So far, we could use mixins, scoped slots or higher order components, but all of these have their cons. This feature is inspired by React’s Hooks, but a bit better, as it avoids a few caveats. For instance, Vue’s hooks will not be called on every render, but instead just once, in the setup method. Thanks to that, there will be less work for the garbage collector.

In addition, they can be used conditionally, are not sensitive to call order, and avoid an issue with stale values. You can find more about the differences in Composition API’s documentation. I have already written an article dedicated to Composition API and how it can be used. You can find it here.

Decoupled Packages

In Vue 3, internal packages are split into separate files. This will result in more modular and maintainable source code for the team working on the framework. It will also make it easier to use Vue’s renderer on different targets than just web. Good examples are Weex and NativeScript—these are frameworks that utilize Vue for creating mobile apps.

Decoupled Packages

Native Portals

Normally, elements are rendered exactly where they are defined. However, sometimes we would like to render elements somewhere else in an application. For instance, if we have a global modal component, it would be nice to be able to open it and set its content from anywhere in the application. At the moment, this is possible thanks to the portal-vue package. In Vue 3, this feature is provided out of the box, but it’s called Teleport.

// Somewhere high in your app

<div id="teleport-content"></div>

// Further down the app
<Portal target="teleport-content">I was teleported!</Portal>

Fragments

At the moment, a Vue template must always have one root element like so:

// One root element only in a template
<template>
	<div>
	</div>
<template>

Inspired by React’s Fragments, Vue 3 will allow multiple root nodes. This is very useful especially for list and table elements, as, for instance, a table row or a list element shouldn’t have a div as a parent.

// This works in Vue 3
<template>
	<li>
	</li>
	<li>
	</li>
</template

In Vue 2, to achieve the same outcome, a functional component would need to be used:

export default {
	functional: true,
	render(h) {
        return [
          h("li", {
            domProps: {
              textContent: "first li"
            }
          }),
          h("li", {
            domProps: {
              textContent: "second li"
            }
          })
        ];
  	}
}

Global Mounting

Most Vue projects start in the main.js file where the global Vue instance is created and mounted. Other libraries and plugins would also be added to this Vue instance. In Vue 3, a method called createApp will be used to create a Vue app instead. The benefit of this is the fact that third-party libraries will not be able to make changes to our app instance—for example, by using global mixins, filters or directives.

Multiple v-models

Currently, only one v-model can be used on a component.

<comp v-model="form" />

Vue 3 will allow us to use multiple v-models on a component.

// Parent component

<template>
	<Form v-model:petName="petName" v-model:petAge="petAge" />
</template>
<script>
export default {
	data() {
		return {
			petName: '',
			petAge: ''
		}
	}
}
.6
</script>

// Form component 
<template>
  <input :value="petName" @input="update('petName', $event.target.value)" />
  <input :value="petAge" @input="update('petAge', +$event.target.value)" type="number" />
</template>

<script>
export default {
  name: "Form",
  props: {
    petName: String,
    petAge: Number
  },
  setup(props, context) {
    const { emit } = context;
    const update = (key, value) => {
      emit(`update:${key}`, value);
    };
    return {
      update
    };
  },
};
</script>

New Custom Directives API

The API for creating custom directives will be changed to better align with Vue’s lifecycle hooks.

Vue 2

const vue2directive = {
	bind(el, binding, vnode, prevNode) {},
	inserted() {},
    update() {},
    componentUpdated() {},
    unbind() {}	
}


Vue 3

const vue3directive = {
  beforeMount(el, binding, vnode, prevVnode) {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeUnmount() {},
  unmounted() {}
}

New Lifecycle Method—renderTriggered

Sometimes a component might render and we might not know why. renderTriggered is a new lifecycle hook that can be used to find that out.

const vm = {
	renderTriggered(e) {
		console.log(`${this.$options.name} was triggered`, e)
	}
}

Suspense

Suspense is another new component added to Vue 3. Suspense component will allow displaying a fallback content while the component passed in the default slot is being loaded.

<template>
	<Suspense>
		<template #default>
			// Component that is being loaded
		</template>
		<template #default>
			// Fallback content displayed while other component is being loaded
		</template>
	</Suspense>
</template>

Conclusion

Vue 3 is much faster and smaller, and it will offer a lot of improvements over its predecessor, as well as bring new useful and exciting features that will allow us to write cleaner and more maintainable code. You can already start using Vue 3 by using vue-cli or Vite, a new build tool created by Evan You.


Thomas Findlay
About the Author

Thomas Findlay

Thomas Findlay is a web and mobile developer, mentor, technical writer and consultant with almost six years of experience. He specializes in frontend web technologies including Vue.js, React.js, React Native for mobile applications, along with backend: PHP, Laravel, Python, Flask, Node.js and Express.js. Thomas has designed and developed websites and mobile applications for individuals and small and large businesses. Learn more about Thomas at https://www.codementor.io/thomas478

Related Posts

Comments

Comments are disabled in preview mode.