1. 架構設計差異

Vue2 的 Options API

Vue2 採用 Options API 組織代碼,通過不同的選項(data、methods、computed 等)來定義組件:

// Vue2 Options API
export default {
  data() {
    return {
      count: 0,
      message: 'Hello Vue2'
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  computed: {
    doubledCount() {
      return this.count * 2
    }
  },
  mounted() {
    console.log('Component mounted')
  }
}

Vue3 的 Composition API

Vue3 引入了 Composition API,提供更靈活的代碼組織方式:

// Vue3 Composition API
import { ref, computed, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const message = ref('Hello Vue3')
    
    const increment = () => {
      count.value++
    }
    
    const doubledCount = computed(() => count.value * 2)
    
    onMounted(() => {
      console.log('Component mounted')
    })
    
    return {
      count,
      message,
      increment,
      doubledCount
    }
  }
}

優勢對比:

  • 更好的邏輯複用:Composition API 使得提取和重用邏輯變得更加容易
  • 更靈活的代碼組織:相關功能可以組織在一起,而不是分散在不同的選項中
  • 更好的 TypeScript 支持:類型推斷更加準確和自然

2. 響應式系統重寫

Vue2 的響應式原理

Vue2 使用 Object.defineProperty 實現響應式:

// Vue2 響應式原理簡化版
function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log(`讀取 ${key}: ${val}`)
      return val
    },
    set(newVal) {
      console.log(`設置 ${key}: ${newVal}`)
      val = newVal
      // 觸發更新
    }
  })
}

侷限性:

  • 無法檢測對象屬性的添加或刪除
  • 對數組的索引修改和長度修改無法追蹤
  • 需要額外的 $set$delete 方法

Vue3 的 Proxy 實現

Vue3 使用 ES6 的 Proxy 重構響應式系統:

// Vue3 響應式原理簡化版
function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      console.log(`讀取 ${String(key)}`)
      return Reflect.get(target, key, receiver)
    },
    set(target, key, value, receiver) {
      console.log(`設置 ${String(key)}: ${value}`)
      const result = Reflect.set(target, key, value, receiver)
      // 觸發更新
      return result
    }
  })
}

優勢:

  • 支持對象和數組的全方位監聽
  • 性能更好,特別是對於大型對象
  • 無需特殊 API 處理新增/刪除屬性

3. 性能優化

編譯時優化

Vue3 在編譯階段進行了多項優化:

  1. 靜態樹提升(Static Tree Hoisting)

    // Vue3 會將靜態內容提升到渲染函數外
    const _hoisted_1 = /*#__PURE__*/_createVNode("div", null, "靜態內容")
    
  2. 補丁標誌(Patch Flags)

    // Vue3 在編譯時標記動態內容,減少運行時比較
    _createVNode("div", { 
      id: _ctx.id,
      class: _ctx.className 
    }, null, 8 /* PROPS */, ["id", "class"])
    
  3. 樹結構拍平(Tree Flattening)

    • 只追蹤動態子節點,減少虛擬 DOM 遍歷深度

體積優化

  • Vue3 通過 Tree-shaking 支持,未使用的功能不會打包到最終產物中
  • 相比 Vue2,運行時體積減少約 41%

4. TypeScript 支持

Vue2 的 TypeScript 支持

Vue2 對 TypeScript 的支持需要通過裝飾器實現:

// Vue2 + TypeScript
import { Component, Vue } from 'vue-property-decorator'

@Component
export default class MyComponent extends Vue {
  private count: number = 0
  
  private increment(): void {
    this.count++
  }
}

Vue3 的原生 TypeScript 支持

Vue3 使用 TypeScript 重寫,提供更好的類型推斷:

// Vue3 + TypeScript
import { defineComponent, ref } from 'vue'

interface User {
  name: string
  age: number
}

export default defineComponent({
  setup() {
    const count = ref<number>(0)
    const user = ref<User>({
      name: 'John',
      age: 25
    })
    
    const increment = (): void => {
      count.value++
    }
    
    return {
      count,
      user,
      increment
    }
  }
})

5. 新的組件和 API

Fragment 片段

Vue3 支持多根節點組件:

<!-- Vue3 Fragment -->
<template>
  <header>頭部</header>
  <main>主要內容</main>
  <footer>底部</footer>
</template>

Teleport 傳送

將組件渲染到 DOM 中的其他位置:

<template>
  <div class="modal-container">
    <Teleport to="body">
      <div class="modal">
        模態框內容
      </div>
    </Teleport>
  </div>
</template>

Suspense 異步組件

更好的異步組件加載體驗:

<template>
  <Suspense>
    <template #default>
      <AsyncComponent />
    </template>
    <template #fallback>
      <div>加載中...</div>
    </template>
  </Suspense>
</template>

6. 生命週期變化

Vue2 生命週期

export default {
  beforeCreate() {},
  created() {},
  beforeMount() {},
  mounted() {},
  beforeUpdate() {},
  updated() {},
  beforeDestroy() {},
  destroyed() {}
}

Vue3 生命週期

import { onMounted, onUpdated, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('組件掛載')
    })
    
    onUpdated(() => {
      console.log('組件更新')
    })
    
    onUnmounted(() => {
      console.log('組件卸載')
    })
  }
}

主要變化:

  • beforeDestroyonBeforeUnmount
  • destroyedonUnmounted

7. 遷移指南

漸進式遷移策略

  1. 使用兼容版本:Vue2.7 提供了部分 Vue3 特性的向後兼容
  2. 混合使用:在 Vue2 項目中逐步引入 Composition API
  3. 使用遷移構建版本:Vue3 提供了兼容 Vue2 的構建版本

常見 API 變化

// Vue2
this.$set(this.obj, 'key', value)
this.$delete(this.obj, 'key')

// Vue3
import { set, del } from 'vue'
set(obj, 'key', value)
del(obj, 'key')

// 事件總線
// Vue2
Vue.prototype.$bus = new Vue()

// Vue3
import mitt from 'mitt'
app.config.globalProperties.$bus = mitt()

8. 實際應用示例

邏輯複用對比

Vue2 Mixins:

// counterMixin.js
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}

// 使用
import counterMixin from './counterMixin'
export default {
  mixins: [counterMixin]
}

Vue3 Composables:

// useCounter.js
import { ref } from 'vue'

export function useCounter() {
  const count = ref(0)
  
  const increment = () => {
    count.value++
  }
  
  return {
    count,
    increment
  }
}

// 使用
import { useCounter } from './useCounter'
export default {
  setup() {
    const { count, increment } = useCounter()
    return { count, increment }
  }
}

總結

Vue3 在保留 Vue2 核心概念的同時,通過架構重構帶來了顯著的性能提升和更好的開發體驗。主要優勢包括:

  1. 更好的性能:更小的包體積、更快的渲染速度
  2. 更好的 TypeScript 支持:完整的類型推斷和類型安全
  3. 更好的邏輯複用:Composition API 提供更靈活的邏輯組織方式
  4. 更好的可維護性:相關功能集中管理,代碼更清晰

對於新項目,強烈推薦直接使用 Vue3。對於現有 Vue2 項目,可以根據實際情況制定漸進式遷移計劃。