阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 与Vue2架构的主要区别

与Vue2架构的主要区别

作者:陈川 阅读数:12942人阅读 分类: Vue.js

响应式系统的重构

Vue3 使用 Proxy 替代了 Vue2 的 Object.defineProperty 实现响应式。Proxy 可以拦截整个对象,不需要递归遍历所有属性,性能更好。Vue2 中需要显式调用 Vue.set 来添加新属性响应式,而 Vue3 中直接赋值即可。

// Vue2
this.$set(this.someObject, 'newProperty', value)

// Vue3
this.someObject.newProperty = value // 自动响应

Proxy 还能检测到数组索引变化和 length 变化,Vue2 中需要重写数组方法来实现响应式。Vue3 的响应式系统还支持 Map、Set 等集合类型。

Composition API 的引入

Vue3 新增了 Composition API,作为 Options API 的补充。Composition API 通过 setup 函数组织代码,相关逻辑可以集中在一起,而不是分散在 data、methods 等选项中。

// Vue2 Options API
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}

// Vue3 Composition API
import { ref } from 'vue'

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

Composition API 更适合复杂组件,逻辑可以提取为可复用的函数,解决了 Vue2 中 mixins 的命名冲突和来源不清晰问题。

虚拟 DOM 的优化

Vue3 重写了虚拟 DOM 的实现,引入了静态提升和补丁标志等优化。模板中的静态节点会被提升到渲染函数外,避免重复创建。编译器会分析动态绑定,生成带有补丁标志的代码,运行时可以跳过静态子树。

// 编译后的渲染函数示例
function render() {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("h1", null, "Static Title"), // 静态提升
    _createVNode("p", { class: _ctx.dynamicClass }, _toDisplayString(_ctx.message), 1 /* TEXT */)
  ]))
}

Vue3 还支持片段(Fragment),组件可以有多个根节点,不再需要额外包裹 div。

性能提升

Vue3 在多个方面进行了性能优化:

  1. 更小的包体积:Tree-shaking 支持更好,未使用的 API 不会打包
  2. 更快的初始渲染:编译器优化减少了约 40% 的运行时开销
  3. 更低的内存占用:响应式系统更高效
  4. 更快的更新:靶向更新只处理动态部分

TypeScript 支持

Vue3 使用 TypeScript 重写,提供了更好的类型推断。Composition API 的设计考虑了类型推导,ref 和 reactive 都有完整的类型支持。

import { ref } from 'vue'

const count = ref(0) // Ref<number>
count.value = 'string' // 类型错误

Vue2 虽然也能用 TypeScript,但需要额外装饰器或 class 组件,类型支持不完整。

自定义渲染器 API

Vue3 将核心逻辑与 DOM 渲染分离,暴露了自定义渲染器 API。可以基于相同响应式系统构建非 DOM 环境的渲染器,如小程序、Canvas 或原生应用。

import { createRenderer } from 'vue'

const { render, createApp } = createRenderer({
  patchProp,
  insert,
  remove,
  createElement
  // ...其他平台特定方法
})

全局 API 变更

Vue3 调整了全局 API 的组织方式,改为应用实例 API。Vue2 的全局配置会影响所有实例,而 Vue3 每个应用有独立配置。

// Vue2
Vue.config.ignoredElements = [/^app-/]
Vue.directive('focus', { /* ... */ })

// Vue3
const app = createApp(App)
app.config.isCustomElement = tag => tag.startsWith('app-')
app.directive('focus', { /* ... */ })

生命周期调整

Vue3 的生命周期有所变化,beforeDestroy 改为 beforeUnmount,destroyed 改为 unmounted。新增了 renderTracked 和 renderTriggered 调试钩子。

export default {
  setup() {
    onMounted(() => {
      console.log('组件挂载')
    })
    onUnmounted(() => {
      console.log('组件卸载')
    })
  }
}

模板指令变化

v-model 进行了重大调整,支持多个 v-model 绑定,默认使用 modelValue 替代 value:

<!-- Vue2 -->
<input v-model="message">

<!-- Vue3 默认 -->
<input v-model="message">
<!-- 多个 v-model -->
<CustomComponent v-model:title="title" v-model:content="content" />

v-for 的 key 现在应该放在 template 标签上,而不是子元素。v-if 和 v-for 的优先级也发生了变化,v-if 现在有更高优先级。

异步组件改进

Vue3 提供了 defineAsyncComponent 方法来定义异步组件,支持更灵活的加载状态处理:

import { defineAsyncComponent } from 'vue'

const AsyncComp = defineAsyncComponent({
  loader: () => import('./Foo.vue'),
  loadingComponent: LoadingComponent,
  errorComponent: ErrorComponent,
  delay: 200,
  timeout: 3000
})

相比 Vue2 的简单函数形式,Vue3 的异步组件配置更丰富。

Teleport 组件

新增 <teleport> 组件(原名为 portal),可以将子组件渲染到 DOM 中的其他位置,适合模态框、通知等需要突破层级限制的场景。

<teleport to="body">
  <div class="modal" v-if="showModal">
    Modal Content
  </div>
</teleport>

Suspense 组件

实验性的 <suspense> 组件可以协调多个嵌套异步依赖的加载状态,在等待异步组件或 async setup 时显示备用内容。

<suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    Loading...
  </template>
</suspense>

单文件组件改进

Vue3 的单文件组件支持多个根节点,style 标签现在可以包含全局规则或作用域规则。script 部分可以使用 Composition API 的 setup 语法糖:

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

<style scoped>
button {
  color: red;
}
</style>

自定义元素交互

Vue3 提供了更好的 Web Components 支持,通过 defineCustomElement 方法可以将 Vue 组件转换为自定义元素:

import { defineCustomElement } from 'vue'

const MyVueElement = defineCustomElement({
  props: { msg: String },
  template: `<div>{{ msg }}</div>`
})

customElements.define('my-vue-element', MyVueElement)

编译器优化标志

Vue3 的模板编译器会生成带有优化提示的代码,运行时可以根据这些提示进行更高效的更新。例如标记静态节点、动态 props 等:

export function render(_ctx, _cache) {
  return (_openBlock(), _createBlock("div", null, [
    _createVNode("span", { class: _ctx.class }, null, 2 /* CLASS */)
  ]))
}

过渡动画变化

transition 组件相关类名变更,v-enter 改为 v-enter-from,v-leave 改为 v-leave-from。新增了 transition 作为根组件的过渡效果。

<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>

事件 API 调整

Vue3 移除了 $on、$off 和 $once 方法,推荐使用外部库实现事件总线。emit 现在需要在 emits 选项中声明,提供更好的文档化和类型检查。

export default {
  emits: ['submit'], // 显式声明
  setup(props, { emit }) {
    const onSubmit = () => {
      emit('submit', payload)
    }
  }
}

插件系统变化

Vue3 的插件安装方式改变,不再调用 Vue.use(),而是在应用实例上调用 use() 方法:

// Vue2
Vue.use(MyPlugin)

// Vue3
const app = createApp(App)
app.use(MyPlugin)

插件定义也相应调整,install 方法接收应用实例而非 Vue 构造函数。

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌