阿里云主机折上折
  • 微信号
Current Site:Index > The main differences compared to the Vue 2 architecture

The main differences compared to the Vue 2 architecture

Author:Chuan Chen 阅读数:12943人阅读 分类: Vue.js

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:

  1. Smaller bundle size: Better tree-shaking support ensures unused APIs are not included.
  2. Faster initial rendering: Compiler optimizations reduce runtime overhead by about 40%.
  3. Lower memory usage: The reactivity system is more efficient.
  4. 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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.