Unlock Vue 3: TypeScript, Reactive System, Performance Boosts & Composition API
This article explores Vue 3’s built‑in TypeScript support, its new Proxy‑based reactivity, performance improvements such as static patch flags and hoisting, tree‑shaking capabilities, and practical usage of the Composition API with code examples and migration tips from Vue 2.
Introduction
Vue 3 has been released for a while; this article summarises its key improvements from the following perspectives:
Full TypeScript support
New data reactivity system
Performance optimisation
Tree shaking
Composition API
Full TypeScript Support
Vue 2’s TypeScript support required additional decorators such as vue-class-component, vue-property-decorator and vuex-class, plus complex Webpack configuration. Vue 3 removes this friction: the Vue CLI bundles TypeScript tooling out of the box, and the framework itself is written in TypeScript, making it a first‑class citizen.
Defining a component with TypeScript in Vue 3 looks like this:
import { defineComponent, PropType } from 'vue';
interface Student {
name: string;
address: string;
age: number;
}
const Component = defineComponent({
// type inference is enabled automatically
props: {
success: { type: String },
callback: { type: Function as PropType<() => void> },
student: { type: Object as PropType<Student>, required: true }
},
data() {
return { message: 'Vue3 code style' };
},
computed: {
reversedMessage(): string {
return this.message.split(' ').reverse().join('');
}
}
});New Reactivity System
Vue 2 achieved reactivity with Object.defineProperty, which required recursively converting every property and could not detect array changes or dynamically added properties without extra work.
Vue 3 replaces this with ES6 Proxy, intercepting all operations on an object, including newly added properties, without the need for re‑definition:
const obj = { name: 'whisky', age: '27', alcohol: [{ name: 'Macallan' }, { name: 'Romance' }] };
const p = new Proxy(obj, {
get(target, propKey, receiver) {
console.log('you accessed', propKey);
return Reflect.get(target, propKey, receiver);
},
set(target, propKey, value, receiver) {
console.log('you set', propKey, '=', value);
return Reflect.set(target, propKey, value, receiver);
}
});
p.age = '20'; // logs setting and accessing
p.newPropKey = 'new'; // no extra re‑definition neededPerformance Optimisation
Compared with Vue 2, Vue 3 roughly doubles performance thanks to several techniques:
Static PatchFlags
The diff algorithm now marks static nodes with PatchFlags, allowing the renderer to skip them during updates. Vue 2 performed a full‑tree comparison for every render.
export const enum PatchFlags {
TEXT = 1,
CLASS = 1 << 1,
STYLE = 1 << 2,
PROPS = 1 << 3,
FULL_PROPS = 1 << 4,
HYDRATE_EVENTS = 1 << 5,
STABLE_FRAGMENT = 1 << 6,
KEYED_FRAGMENT = 1 << 7,
UNKEYED_FRAGMENT = 1 << 8,
NEED_PATCH = 1 << 9,
DYNAMIC_SLOTS = 1 << 10,
HOISTED = -1,
BAIL = -2
}Event Binding Optimisation
Static event handlers are cached in _cache, preventing repeated creation of identical listeners.
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", _hoisted_1, [
_createVNode("button", {
onClick: _cache[1] || (_cache[1] = $event => (_ctx.confirmHandler($event)))
}, "Confirm"),
_createVNode("span", null, _toDisplayString(_ctx.vue3), 1 /* TEXT */)
]))
}Static Hoisting (hoistStatic)
Static elements are hoisted so they are created only once and reused across renders:
const _hoisted_1 = /*#__PURE__*/_createVNode("div", null, "Static Hoist", -1 /* HOISTED */)Tree Shaking
Tree shaking removes dead code during bundling. For example, if Vue.nextTick is never used, it can be omitted, reducing bundle size. Vue 3 reorganises its API to be fully tree‑shakable:
import { nextTick } from 'vue';
nextTick(() => {
// DOM‑related operations
});Composition API & Practical Example
Motivation
In large Vue 2 projects, mixing data, computed, and methods across many components can become hard to maintain. The Composition API lets developers group related logic together.
Implementation
A ToDo list built with the Options API is shown first, followed by its Composition API counterpart that uses ref, reactive, computed, and toRefs:
<script>
import { ref, reactive, computed, toRefs } from "vue";
export default {
setup() {
const test = ref('this is test');
const state = reactive({
todos: [],
newTodo: '',
editTodo: ''
});
const remaining = computed(() => state.todos.filter(t => !t.completed).length);
const allDone = computed({});
function addTodo() {}
function removeTodo() {}
function editTodo() {}
return { ...toRefs(state), remaining, allDone, addTodo, removeTodo, editTodo };
}
};
</script>The article summarises the differences: the new setup function replaces beforeCreate and created, lifecycle hooks are imported individually (e.g., onMounted), and the API encourages a hook‑like style.
Lifecycle Changes
Vue 3 maps Vue 2 lifecycle hooks as follows:
Vue2 → Vue3
beforeCreate → setup()
created → setup()
beforeMount → onBeforeMount
mounted → onMounted
beforeUpdate → onBeforeUpdate
updated → onUpdated
beforeDestroy → onBeforeUnmount
destroyed → onUnmounted
activated → onActivated
deactivated → onDeactivated
errorCaptured → onErrorCapturedConclusion
Vue 3 has been out for over a year, and its TypeScript integration, Proxy‑based reactivity, performance enhancements, tree‑shaking friendliness, and Composition API provide a compelling upgrade path for modern frontend development.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
BaiPing Technology
Official account of the BaiPing app technology team. Dedicated to enhancing human productivity through technology. | DRINK FOR FUN!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
