Vue3 Introduction
Vue3 is a progressive framework for building user interfaces.
ProgressiveIt means you can introduce only part of Vue's capabilities according to your project needs: from a simple page interaction enhancement, to building complete single-page applications (SPA), and even server-side rendering (SSR) applications, Vue3 is fully capable.
Vue3 is a progressive JavaScript front-end framework led by Evan You, officially released on September 18, 2020, with the codenameOne Piece。
Compared to Vue2, Vue3 completely rewrote the core architecture: the reactivity system went fromObject.definePropertyupgraded toProxy, introducing the Composition API, and comprehensively improving performance, TypeScript support, bundle size, and more.

Vue3's official positioning is:a framework that is easy to get started with, yet has enough power to support complex projects. It neither forces a specific architecture like Angular, nor requires heavy manual optimization like React; instead, it strikes a balance between ease of use and capability.
Essential Differences Between Vue3 and Vue2
Vue3 is not a patch upgrade of Vue2, but a complete rewrite.
| Comparison Item | Vue2 | Vue3 |
|---|---|---|
| Reactivity Principle | Object.defineProperty, cannot observe newly added properties and array index changes | Proxy, completely proxies all operations on the object, without the above limitations |
| Code Organization | Options API: data, methods, and computed are separated | Composition API: code is aggregated by logical concerns |
| TypeScript Support | Adapted later, limited type inference | Core code rewritten in TypeScript, TS is a first-class citizen |
| Bundle Size | Runtime approximately 20KB (gzip) | Supports Tree-shaking, on-demand bundling, minimum only 13.5KB |
| Performance | Baseline | Initial rendering is about 55% faster, update rendering is about 133% faster, memory usage is reduced by about 54% |
| Component Template Root Node | Must have exactly one root element | Supports multiple root nodes (Fragment) |
| Global API | Mounted on the Vue constructor, multiple instances share state | ThroughcreateAppcreating independent instances, with more thorough isolation |
Core Features
Vue3's improvements span four dimensions: the reactivity system, API design, the compiler, and new built-in components.
Composition API
Composition API is the most important design change in Vue3; it solves the fundamental pain points of the Options API in Vue2:Related logic is scattered across different options, making reuse difficult。
In the Options API, the data for a "user search" feature may be scattered acrossdata、methods、computed、watchfour options; whereas Composition API allows you to write all the logic for the same feature together, and then extract it into reusable functions (Composables).
Example: Options API vs Composition API
<script>
export default {
data() {
return {
count: 0, // counter data
username: 'example' // username data
}
},
computed: {
doubled() { // double of count
return this.count * 2
}
},
methods: {
increment() { // increment the count
this.count++
}
}
}
</script>
Example: Recommended Approach (script setup Syntax Sugar)
<script setup>
import { ref, computed } from 'vue'
// Reactive data is declared directly, no need to return
const count = ref(0) // ref wraps primitive types
const username = ref('example')
// computed property
const doubled = computed(() => count.value * 2)
// Methods are defined directly as functions
function increment() {
count.value++ // Note: ref-wrapped values must be accessed through .value
}
</script>
<template>
<!-- In templates, ref is automatically unwrapped, no need for .value -->
<p>User: {{ username }}</p>
<p>Count: {{ count }}, double: {{ doubled }}</p>
<button @click="increment">+1</button>
</template>
<script setup>is syntax sugar for the Composition API: it lets you<script>directly write Composition API code at the top level, without manuallyreturn, all top-level variables and functions are automatically exposed to the template. This is currently the most recommended way to write single-file components in Vue3.
Reactivity System: Proxy Replaces defineProperty
Vue2's reactivity is based onObject.defineProperty, this approach has two issues that cannot be fundamentally solved: it cannot observe newly added object properties, and it cannot observe direct assignment to array elements by index. Vue3 usesProxyto fundamentally solve these two problems.
Example: ref and reactive
// ref: suitable for primitive types (number, string, boolean)
// Accessing and modifying values requires .value
const count = ref(0)
count.value = 10
// reactive: suitable for objects and arrays
// Access properties directly, no need for .value
const user = reactive({
name: 'EXAMPLE',
age: 18,
skills: ['vue', 'typescript']
})
// In Vue3, you can add new properties to an object and reactivity still works normally
user.email = 'example@example.com' // In Vue2, this operation does not trigger view updates
// You can also modify array elements directly
user.skills[0] = 'vue3' // In Vue2, this operation does not trigger view updates
// Watch reactive data changes
watch(count, (newVal, oldVal) => {
console.log(`count from ${oldVal}to ${newVal}`)
})
Composable Functions (Composables)
Composables are the standard way to reuse stateful logic in Vue3, similar to React's custom Hooks.
It is conventional touseprefix the name, extract a complete piece of reactive logic into an independent function, and reuse it across multiple components.
Example: Custom Composable
// Encapsulate counter logic; any component can reuse it
import { ref, computed } from 'vue'
export function useCounter(initialValue = 0) {
const count = ref(initialValue) // Internal reactive state
const doubled = computed(() => count.value * 2) // Derived state
function increment() { count.value++ }
function decrement() { count.value-- }
function reset() { count.value = initialValue }
// Return the state and methods that need to be exposed externally
return { count, doubled, increment, decrement, reset }
}
Example: Using Composable in Components
import { useCounter } from './composables/useCounter'
// Destructure and use directly; reactivity is preserved
const { count, doubled, increment, decrement, reset } = useCounter(10)
</script>
<template>
<p>Current value: {{ count }}, doubled: {{ doubled }}</p>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<button @click="reset">Reset</button>
</template>
New Built-in Components
Vue3 introduces three new built-in components that solve three high-frequency scenarios in frontend development.
| Component | Problem Solved | Typical Use Cases |
|---|---|---|
| Fragment | Vue2 required component templates to have a single root node; Fragment allows multiple root nodes to coexist (no extra wrapping div needed) | List item components, reducing unnecessary DOM nesting |
| Teleport | Renders a component's HTML to any specified position in the DOM, breaking through the parent component's CSS stacking context limitations | Global Modal dialogs, Toast notifications, floating toolbars |
| Suspense | Gracefully displays fallback content before async components finish loading, uniformly handling async waiting states | Skeleton screens for lazy-loaded components, loading indicators during route transitions |
Example: Using Teleport to Implement a Global Modal
import { ref } from 'vue'
const showModal = ref(false)
</script>
<template>
<button @click="showModal = true">Open Modal</button>
<!--
Teleport mounts the modal content under body,
rather than inside the current component's parent element, avoiding z-index and overflow issues
-->
<Teleport to="body">
<div v-if="showModal" class="modal-mask">
<div class="modal-box">
<p>This is a global modal</p>
<button @click="showModal = false">Close</button>
</div>
</div>
</Teleport>
</template>
Example: Using Suspense to Handle Async Component Loading
<template>
<Suspense>
<!-- Default slot: async content -->
<template #default>
<AsyncUserProfile /> <!-- Async components that use await internally -->
</template>
<!-- fallback slot: content shown while loading -->
<template #fallback>
<div class="loading">Loading...</div>
</template>
</Suspense>
</template>
Tree-shaking Support
Vue3 changes all global APIs to named exports. With the tree-shaking capability of bundlers like Vite / webpack, unused APIs are not bundled into the final output.
Example: Importing APIs on Demand
// Vue.nextTick(...)
// Vue.set(obj, 'key', value)
// Vue3: Import on demand; only the functions actually used are included in the bundle
import { ref, computed, watch, nextTick, onMounted } from 'vue'
// Only these APIs are imported; unused ones (such as watchEffect, provide, etc.) will not be included in the bundle
Lifecycle Hooks
All lifecycle hooks corresponding to Vue3's Composition API are prefixed withonand are called withinsetupsetup().
| Vue2 Options API | Vue3 Composition API | Trigger Timing |
|---|---|---|
beforeCreate | — (setup itself replaces this) | Before instance initialization |
created | — (setup itself replaces this) | Instance created |
beforeMount | onBeforeMount | Before mount |
mounted | onMounted | Mounted, DOM accessible |
beforeUpdate | onBeforeUpdate | Before data updates and DOM re-render |
updated | onUpdated | After DOM re-render completes |
beforeDestroy | onBeforeUnmount | Before component unmount (name changed) |
destroyed | onUnmounted | Component unmount complete (name changed) |
Example: Using Lifecycle Hooks
import { ref, onMounted, onUnmounted } from 'vue'
const timer = ref(null)
const count = ref(0)
// Executed after the component is mounted (DOM can be safely manipulated)
onMounted(() => {
console.log('Component mounted')
// Start a timer that increments the count every second
timer.value = setInterval(() => {
count.value++
}, 1000)
})
// Executed when the component unmounts (clean up side effects to avoid memory leaks)
onUnmounted(() => {
clearInterval(timer.value)
console.log('Timer cleared')
})
</script>
<template>
<p>Running for: {{ count }} seconds</p>
</template>
Full TypeScript Support
Vue3's core library is completely rewritten in TypeScript, providing precise type inference. Combined with<script setup lang="ts">, you can use TypeScript directly in single-file components without additional configuration.
Example: Using TypeScript in script setup
import { ref, computed } from 'vue'
// Interface defining the data structure within the component
interface User {
id: number
name: string
email?: string
}
// ref automatically infers the type from the initial value, or it can be explicitly specified
const user = ref<User>({
id: 1,
name: 'EXAMPLE',
})
// defineProps: declare and infer prop types
const props = defineProps<{
title: string //Required
count?: number //Optional
}>()
// defineEmits: declare and type-check custom events
const emit = defineEmits<{
(e: 'update', value: number): void
(e: 'close'): void
}>()
const displayName = computed(() => user.value.name.toUpperCase())
function handleUpdate() {
emit('update', 42)
}
</script>
Application Areas
As a complete frontend framework ecosystem, Vue3 covers a wide range of scenarios, from single-page applications to server-side rendering, from Web to mobile.
Single-page Applications (SPA)
This is the most classic use case for Vue3. Combined withVue Router 4for frontend routing,Pinia(the state management library officially recommended by Vue3, replacing Vuex) to manage global state, you can build fully functional single-page applications.
Typical project types: enterprise admin systems, data dashboards, e-commerce storefronts.
Server-side Rendering (SSR) and Static Site Generation (SSG)
Nuxt 3is a full-stack framework based on Vue3, deeply integrating SSR and SSG capabilities. It automatically handles the complexity of server-side rendering, allowing developers to build SEO-friendly applications just like writing regular Vue components.
Suitable scenarios: content websites, blogs, documentation sites, marketing landing pages.
Mobile and Cross-platform
uni-appSupports using Vue3 syntax to simultaneously develop WeChat Mini Programs, Alipay Mini Programs, H5, and Apps (iOS/Android).Ionic + Vue3is suitable for building high-quality hybrid mobile applications.
Desktop Applications
Electron + Vue3(through toolchains like electron-vite) can package Vue3 applications as cross-platform desktop applications.Tauri + Vue3is a popular alternative in recent years, using Rust as the backend, resulting in smaller application size and better performance.
UI Component Library Ecosystem
The Vue3 ecosystem offers a rich selection of mature component libraries:
| Component Library | Positioning | Suitable Scenarios |
|---|---|---|
| Element Plus | PC desktop component library, the Vue3 version of Element UI | Enterprise admin systems, data-intensive applications |
| Ant Design Vue | Vue implementation of Ant Design, with mature design specifications | Mid/back-office systems, enterprise applications |
| Vant 4 | Mobile component library, lightweight and high-performance | Mobile H5, WeChat Mini Programs |
| Vuetify 3 | Material Design style component library | Consumer-facing web applications |
| Naive UI | Written in TypeScript, with strong theme customization capabilities | Projects requiring deep theme customization |
| shadcn-vue | Based on Radix UI and Tailwind, a collection of copy-paste components | Projects that value UI uniqueness |
Development History
Vue.js grew from a personal project into one of the top three frontend frameworks in the world. Each major version was driven by clear engineering needs.
Origins (2013 - 2014)
Vue.js was created by Evan You during his time at Google. In 2013, he explored the Angular development experience, hoping to extract his favorite part — the data-driven view update mechanism — while removing the parts he considered overly heavy.
In February 2014, Vue.js 0.8.0 was publicly released. It subsequently gained attention from the Laravel community and gradually became well-known in the JavaScript community.
Vue 1.x Era (2015)
In October 2015, Vue 1.0 was officially released, codenamed Evangelion. That same year,Vue Router(2015.08)、Vuex(2015.11)、Vue CLI(December 2015) were released successively, marking Vue's evolution from a view-layer library into a complete progressive framework.
Vue 2.x Era (2016 - 2020)
In October 2016, Vue 2.0 was released, introducing a virtual DOM approach (inspired by React), supporting server-side rendering (SSR), and significantly improving performance.
The Vue 2 era was the fastest expansion phase of the Vue ecosystem: component libraries such as Element UI emerged, Nuxt.js appeared, and Vue became one of the frontend frameworks with the most GitHub stars in the world.
In February 2019, Vue 2.6 was released, codenamed Macross. This was the last major version of Vue 2, bridging the past and the future.
Vue 3.0 Release (2020)
Vue3 development began in late 2018 and took about two years, going through 30+ RFCs (Request for Comments), 2600+ commits, and 628 PRs from 99 contributors.
On September 18, 2020, Vue 3.0 was officially released, codenamed One Piece. Core changes:
- The reactive system is based on
ProxyRewritten - Introduced Composition API
- Full TypeScript support
- Added Fragment, Teleport, Suspense
- Supports Tree-shaking, significantly reduced bundle size
Ecosystem Maturation Stage (2021 - 2022)
| Time | Version / Event | Milestone significance |
|---|---|---|
| 2021-08 | Vue 3.2 | <script setup>The syntactic sugar officially stabilized,<style> v-bindSupports dynamic CSS binding, became one of the most popular Vue 3 versions |
| 2022-02 | Vue 3 became the default version | On the vue.js official website and npmvueThe default package version switched from 2 to 3, marking the official dominance of the Vue 3 ecosystem |
| 2022-05 | Pinia became the official recommendation | Vuex 5 plans were shelved, Pinia became the officially recommended state management library for Vue 3 |
| 2022 | Vue 3.3 | Enhanced generic component support, improveddefinePropstype inference, significantly improving TypeScript experience |
Continuous Optimization Stage (2023 - Present)
| Time | Version | Key features |
|---|---|---|
| 2023-12 | Vue 3.4 | Rewrote the template parser (performance improved ~2x), reactive system optimization (reduced invalid computation triggers),defineModelThe macro officially stabilized (simplifies v-model two-way binding) |
| 2024-09 | Vue 3.5 | Reactive Props destructuring officially stabilized (destructure while maintaining reactivity without toRef),useTemplateRefNew APIs, SSR Lazy Hydration |
| 2025 (in development) | Vue 3.6 | Integrated Alien Signals reactive system (dependency tracking memory reduced ~14%), Vapor Mode entered Alpha (completely skips virtual DOM, bundle size reduced from 50KB to ~6KB, 100,000 component mount time ~100ms) |
Vapor ModeIs the most important future technical direction for Vue 3: through compile-time static analysis, templates are compiled directly into precise native DOM manipulation code, completely bypassing the virtual DOM creation and diff process. It can coexist with the existing virtual DOM mode and supports progressive migration. Currently only supports
<script setup>Composition API; Options API is not applicable.
Vue3's Position Among the Three Major Frameworks
Vue 3, React, and Angular are the three mainstream frameworks in front-end development. Understanding their positions helps make more appropriate technology selections.
| Comparison dimension | Vue3 | React 18+ | Angular 17+ |
|---|---|---|---|
| Positioning | Progressive framework, officially provides routing and state management | UI library, ecosystem led by community | Complete framework, everything has official solutions |
| Syntax style | Single-file components (.vue), intuitive template syntax | JSX, writing HTML in JavaScript | Components + templates + decorators, high degree of engineering |
| Learning curve | Relatively gentle, template syntax close to HTML | Moderate, requires understanding JSX and Hooks mental models | Steep, many concepts (modules, dependency injection, RxJS) |
| TypeScript | Core library rewritten in TS, good support | Good, requires @types/react | TypeScript by default, deeply integrated |
| Performance | Excellent, fine-grained reactivity, precise updates | Good, React 19 Compiler further optimized | Good, Signals mechanism continuously improving |
| Applicable scale | Suitable for small-to-medium to large projects | All scales, mature cases in ultra-large projects | Large enterprise projects, high team standardization requirements |
| Chinese market share | Highest, widely used by enterprises | High | Relatively low |
In the domestic front-end ecosystem, Vue 3 has the highest usage rate. Component libraries with complete Chinese documentation such as Element Plus and Ant Design Vue have greatly lowered the barrier for enterprise adoption. If your goal is the domestic job market, Vue 3 is one of the frameworks most worth prioritizing.
Vue3's Limitations
Understanding Vue 3's boundaries can help you make more rational technical judgments.
| Limitation | Specific manifestation | Recommendation |
|---|---|---|
| Decision cost of Options API and Composition API coexisting | Two API styles coexist; teams need to agree on unified standards, otherwise code styles will be inconsistent | New projects should uniformly use<script setup> + Composition API |
| Mental burden of .value for reactive data | refNeeded in scripts.value, automatically unwrapped in templates, beginners easily confused | Use the Volar plugin, IDE will provide hints; no longer a problem once you form the habit |
| State management complexity for large applications | Pinia's state management support for ultra-large, high-concurrency scenarios is less mature than Redux | Ultra-large applications can evaluate Pinia + modular split solutions |
| Server-side rendering hydration cost | SSR pages require "hydration", initialization takes longer on low-end devices | Vue 3.5 introduced Lazy Hydration, Vue 3.6's Vapor Mode will further improve this |
| International ecosystem richness | Compared to React, Vue's English community activity and Stack Overflow resources are slightly fewer | Official documentation is extremely high quality, Chinese documentation is complete, prioritize consulting official documentation |