What’s new in Vue 3

Vue 3 was officially released on September 18, 2020. It brings several improvements and changes compared to Vue 2. Here are some of the main differences:

Composition API

Vue 3 introduces the Composition API alongside the Options API. It allows to organize code logic by features rather than by options like in the Options API. That improves code organization and reusability.

Vue 2

<!-- template -->

<button @click="increment">Count is: {{ count }} ({{ oddEven }})</button>

// script

export default {
    data() {
        return {
            count: 0
        }
    },
    computed: {
        oddEvent() {
            return this.count % 2 ? 'odd' : 'even'
        }
    },
    methods: {
        increment() {
            this.count++
        }
    },
    mounted() {
        console.log(`The initial count is ${this.count}.`)
    }
}

Vue 3

<!-- template -->

<button @click="increment">Count is: {{ count }} ({{ oddEven }})</button>

// script setup

import { ref, computed, onMounted } from 'vue'

const count = ref(0)

const oddEven = computed(() => count.value % 2 ? 'odd' : 'even')

const increment = () => {
    count.value++
}

onMounted(() => {
    console.log(`The initial count is ${this.count}.`)
})

Teleport

It is a component that allows to render its children to a target DOM element outside of the DOM hierarchy. This can be useful for modals and tooltips.

Vue 2

<!-- ParentComponent.vue -->

<div class="outer">
    <div>
        <ChildComponent />
    </div>
</div>

<!-- ChildComponent.vue - template -->

<button @click="open = true">Open Modal</button>

<div v-if="open" class="modal">
    <p>Hello from the modal!</p>
    <button @click="open = false">Close</button>
</div>

// ChildComponent.vue - script

export default {
    data() {
        return {
            open: false
        }
    }
}

// ChildComponent.vue - style

.modal {
    position: fixed;
    z-index: 999;
    top: 20%;
    left: 50%;
    width: 300px;
    margin-left: -150px;
}

Vue 3

<!-- ParentComponent.vue -->

<div class="outer">
    <div>
        <ChildComponent />
    </div>
</div>

<!-- ChildComponent.vue - template -->

<button @click="open = true">Open Modal</button>

<Teleport to="body">
    <div v-if="open" class="modal">
        <p>Hello from the modal!</p>
        <button @click="open = false">Close</button>
    </div>
</Teleport>

// ChildComponent.vue - script

export default {
    data() {
        return {
            open: false
        }
    }
}

// ChildComponent.vue - style

.modal {
    position: fixed;
    z-index: 999;
    top: 20%;
    left: 50%;
    width: 300px;
    margin-left: -150px;
}

Fragments

Vue 3 adds support for multi-root node components, called fragments.

Vue 2

<template>
    <div>
        <header>...</header>
        <main>...</main>
        <footer>...</footer>
    </div>
</template>

Vue 3

<template>
    <div>
        <header>...</header>
        <main v-bind="$attrs">...</main>
        <footer>...</footer>
    </div>
</template>

Better TypeScript Support

Vue 3 is written in TypeScript and has improved TypeScript support.

Performance Improvements

Vue 3 is designed with performance in mind. It features a reactivity system rewrite, which improves performance and reduces bundle size.