The main differences compared to the Vue 2 architecture
Refactoring of the Reactive System
Vue 3 replaces Vue 2's Object.defineProperty
with Proxy
to implement reactivity. Proxy
can intercept the entire object without recursively traversing all properties, resulting in better performance. In Vue 2, you needed to explicitly call Vue.set
to make new properties reactive, whereas in Vue 3, direct assignment works automatically.
// Vue 2
this.$set(this.someObject, 'newProperty', value)
// Vue 3
this.someObject.newProperty = value // Automatically reactive
Proxy
can also detect array index changes and length
modifications, which in Vue 2 required overriding array methods to achieve reactivity. Vue 3's reactivity system also supports collection types like Map
and Set
.
Introduction of the Composition API
Vue 3 introduces the Composition API as a complement to the Options API. The Composition API organizes code through the setup
function, allowing related logic to be grouped together rather than scattered across data
, methods
, and other options.
// Vue 2 Options API
export default {
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
}
// Vue 3 Composition API
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
const increment = () => count.value++
return { count, increment }
}
}
The Composition API is better suited for complex components, as logic can be extracted into reusable functions, addressing the naming conflicts and unclear origins associated with mixins in Vue 2.
Virtual DOM Optimizations
Vue 3 rewrites the virtual DOM implementation, introducing optimizations like static hoisting and patch flags. Static nodes in templates are hoisted outside the render function to avoid redundant creation. The compiler analyzes dynamic bindings and generates code with patch flags, allowing the runtime to skip static subtrees.
// Example of a compiled render function
function render() {
return (_openBlock(), _createBlock("div", null, [
_createVNode("h1", null, "Static Title"), // Static hoisting
_createVNode("p", { class: _ctx.dynamicClass }, _toDisplayString(_ctx.message), 1 /* TEXT */)
]))
}
Vue 3 also supports Fragments, allowing components to have multiple root nodes without needing an extra wrapper div
.
Performance Improvements
Vue 3 introduces optimizations in several areas:
- Smaller bundle size: Better tree-shaking support ensures unused APIs are not included.
- Faster initial rendering: Compiler optimizations reduce runtime overhead by about 40%.
- Lower memory usage: The reactivity system is more efficient.
- Faster updates: Targeted updates only process dynamic parts.
TypeScript Support
Vue 3 is rewritten in TypeScript, providing better type inference. The Composition API is designed with type derivation in mind, with full type support for ref
and reactive
.
import { ref } from 'vue'
const count = ref(0) // Ref<number>
count.value = 'string' // Type error
While Vue 2 could also use TypeScript, it required additional decorators or class components, and type support was incomplete.
Custom Renderer API
Vue 3 decouples core logic from DOM rendering, exposing a Custom Renderer API. This allows building renderers for non-DOM environments (e.g., mini-programs, Canvas, or native applications) using the same reactivity system.
import { createRenderer } from 'vue'
const { render, createApp } = createRenderer({
patchProp,
insert,
remove,
createElement
// ...Other platform-specific methods
})
Global API Changes
Vue 3 reorganizes global APIs into application instance APIs. In Vue 2, global configurations affected all instances, whereas in Vue 3, each app has independent configurations.
// Vue 2
Vue.config.ignoredElements = [/^app-/]
Vue.directive('focus', { /* ... */ })
// Vue 3
const app = createApp(App)
app.config.isCustomElement = tag => tag.startsWith('app-')
app.directive('focus', { /* ... */ })
Lifecycle Adjustments
Vue 3 renames some lifecycle hooks: beforeDestroy
becomes beforeUnmount
, and destroyed
becomes unmounted
. It also adds debugging hooks like renderTracked
and renderTriggered
.
export default {
setup() {
onMounted(() => {
console.log('Component mounted')
})
onUnmounted(() => {
console.log('Component unmounted')
})
}
}
Template Directive Changes
v-model
undergoes significant changes, supporting multiple bindings and using modelValue
by default instead of value
:
<!-- Vue 2 -->
<input v-model="message">
<!-- Vue 3 (default) -->
<input v-model="message">
<!-- Multiple v-models -->
<CustomComponent v-model:title="title" v-model:content="content" />
The key
in v-for
should now be placed on the template
tag instead of child elements. The precedence of v-if
and v-for
has also changed, with v-if
now having higher priority.
Async Component Improvements
Vue 3 introduces defineAsyncComponent
for defining async components, offering more flexible loading state handling:
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent({
loader: () => import('./Foo.vue'),
loadingComponent: LoadingComponent,
errorComponent: ErrorComponent,
delay: 200,
timeout: 3000
})
Compared to Vue 2's simpler function form, Vue 3's async components are more configurable.
Teleport Component
The new <teleport>
component (originally named portal
) allows rendering child components elsewhere in the DOM, useful for modals, notifications, and other scenarios requiring hierarchy-breaking.
<teleport to="body">
<div class="modal" v-if="showModal">
Modal Content
</div>
</teleport>
Suspense Component
The experimental <suspense>
component coordinates loading states for multiple nested async dependencies, displaying fallback content while waiting for async components or async setup
.
<suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
Loading...
</template>
</suspense>
Single-File Component Enhancements
Vue 3's single-file components support multiple root nodes. The style
tag can now include global or scoped rules. The script
section can use the Composition API's setup
syntactic sugar:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
<style scoped>
button {
color: red;
}
</style>
Custom Element Interoperability
Vue 3 offers better Web Components support. The defineCustomElement
method converts Vue components into custom elements:
import { defineCustomElement } from 'vue'
const MyVueElement = defineCustomElement({
props: { msg: String },
template: `<div>{{ msg }}</div>`
})
customElements.define('my-vue-element', MyVueElement)
Compiler Optimization Flags
Vue 3's template compiler generates code with optimization hints, enabling more efficient updates at runtime. For example, static nodes and dynamic props are flagged:
export function render(_ctx, _cache) {
return (_openBlock(), _createBlock("div", null, [
_createVNode("span", { class: _ctx.class }, null, 2 /* CLASS */)
]))
}
Transition Animation Changes
Transition-related class names are updated: v-enter
becomes v-enter-from
, and v-leave
becomes v-leave-from
. Transitions as root components are now supported.
<transition name="fade">
<div v-if="show">Content</div>
</transition>
<style>
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
</style>
Event API Adjustments
Vue 3 removes $on
, $off
, and $once
methods, recommending external libraries for event buses. emit
now requires declaration in the emits
option for better documentation and type checking.
export default {
emits: ['submit'], // Explicit declaration
setup(props, { emit }) {
const onSubmit = () => {
emit('submit', payload)
}
}
}
Plugin System Changes
Vue 3 changes plugin installation. Instead of Vue.use()
, plugins are installed on the app instance via use()
:
// Vue 2
Vue.use(MyPlugin)
// Vue 3
const app = createApp(App)
app.use(MyPlugin)
Plugin definitions are also adjusted—the install
method receives the app instance instead of the Vue constructor.
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn