V3和V2的区别

Vue3.0 使用 Proxy 实现响应式,性能优化,体积减小,全面支持 TypeScript,引入Composition API,提供Fragment、Teleport等新组件。非兼容变更包括全局API、模板指令和组件的调整,移除了部分旧API。设计目标为更小、更快、更友好,优化了源码管理、性能和语法API。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简版

  1. 性能更高了,主要得益于响应式的原理换成了 proxy,VNode diff 的算法进行了优化。

  2. 体积更小了,删除了一些没必要或不常用到的 API,例如 filter、EventBus 等;按需导入,能配合 Webpack 支持 Tree Shaking。

  3. 对 TS 支持更好啦,因为它本身源码就是用 TS 重写的。

  4. Composition API(组合 API),相比较 Vue2 的 options api,对于开发大型项目更利于代码的复用和维护。

  5. 新特性,例如 Fragment、Teleport、Suspense 等。

一、Vue3 介绍

  关于vue3的重构背景,尤大是这样说的:

        Vue 新版本的理念成型于 2018 年末,当时 Vue 2 的代码库已经有两岁半了。比起通用软件的生命周期来这好像也没那么久,但在这段时期,前端世界已经今昔非比了

        在我们更新(和重写)Vue 的主要版本时,主要考虑两点因素:首先是新的 JavaScript 语言特性在主流浏览器中的受支持水平;其次是当前代码库中随时间推移而逐渐暴露出来的一些设计和架构问题」

简要就是:

  • 利用新的语言特性(es6)
  • 解决架构问题

 vue3 带来的哪些变化

 对于 vue 的高阶开发者

  • 新的 RFC 机制让 Vue 新语法的讨论更加高效和透明
  • Vue3 提供了自定义渲染器让开发跨端应用时更加得心应手。
  • 全部的模块使用 TypeScript 重构,能够带来更好的可维护性。
  • 响应式系统可以单独抽离使用。

 对于 vue 的普通用户

  • 工程化工具 Vite 带来了更丝滑的调试体验。
  • Vue3 内部的优化(响应式系统基于 Proxy,静态标记,tree-shaking 等),使得性能更高,体积更小
  • Composition API 组合语法带来了更好的组织代码的形式。
  • 内置了新的 Fragment、Teleport 和 Suspense 等组件。

 非兼容变更

 Global API

  • 全局 Vue API 已更改为使用应用程序实例
  • 全局和内部 API 已经被重构为可 tree-shakable

  模板指令

  • 组件上 v-model 用法已更改
  • <template v-for>和 非 v-for节点上key用法已更改
  • 在同一元素上使用的 v-if 和 v-for 优先级已更改
  • v-bind="object" 现在排序敏感
  • v-for 中的 ref 不再注册 ref 数组

 组件

  • 只能使用普通函数创建功能组件
  • functional 属性在单文件组件 (SFC)
  • 异步组件现在需要 defineAsyncComponent 方法来创建

 渲染函数

  • 渲染函数API改变
  • $scopedSlots property 已删除,所有插槽都通过 $slots 作为函数暴露
  • 自定义指令 API 已更改为与组件生命周期一致
  • 一些转换 class 被重命名了:
    • v-enter -> v-enter-from
    • v-leave -> v-leave-from
  • 组件 watch 选项和实例方法 $watch不再支持点分隔字符串路径,请改用计算函数作为参数
  • 在 Vue 2.x 中,应用根容器的 outerHTML 将替换为根组件模板 (如果根组件没有模板/渲染选项,则最终编译为模板)。VUE3.x 现在使用应用程序容器的 innerHTML

 其他小改变

  • destroyed 生命周期选项被重命名为 unmounted
  • beforeDestroy 生命周期选项被重命名为 beforeUnmount
  • [prop default工厂函数不再有权访问 this 是上下文
  • 自定义指令 API 已更改为与组件生命周期一致
  • data 应始终声明为函数
  • 来自 mixin 的 data 选项现在可简单地合并
  • attribute 强制策略已更改
  • 一些过渡 class 被重命名
  • 组建 watch 选项和实例方法 $watch不再支持以点分隔的字符串路径。请改用计算属性函数作为参数。
  • <template> 没有特殊指令的标记 (v-if/else-if/elsev-for 或 v-slot) 现在被视为普通元素,并将生成原生的 <template> 元素,而不是渲染其内部内容。
  • Vue 2.x 中,应用根容器的 outerHTML 将替换为根组件模板 (如果根组件没有模板/渲染选项,则最终编译为模板)。Vue 3.x 现在使用应用容器的 innerHTML,这意味着容器本身不再被视为模板的一部分。

 移除 API

  • keyCode 支持作为 v-on 的修饰符
  • $on$off$once 实例方法
  • 过滤filter
  • 内联模板 attribute
  • $destroy 实例方法。用户不应再手动管理单个Vue 组件的生命周期。

 Vue3.0 的设计目标是什么?做了哪些优化 

一、设计目标

不以解决实际业务痛点的更新都是耍流氓,下面我们来列举一下Vue3之前我们或许会面临的问题

  • 随着功能的增长,复杂组件的代码变得越来越难以维护

  • 缺少一种比较「干净」的在多个组件之间提取和复用逻辑的机制

  • 类型推断不够友好

  • bundle的时间太久了

而 Vue3 经过长达两三年时间的筹备,做了哪些事情?

我们从结果反推

  • 更小
  • 更快
  • TypeScript 支持
  • API 设计一致性
  • 提高自身可维护性
  • 开放更多底层功能

一句话概述,就是更小更快更友好了

 更小

  Vue3移除一些不常用的 API

        引入tree-shaking,可以将无用模块“剪辑”,仅打包需要的,使打包的整体体积变小了

 更快

主要体现在编译方面:

  • diff 算法优化
  • 静态提升
  • 事件监听缓存
  • SSR 优化

下篇文章我们会进一步介绍

 更友好

  vue3在兼顾vue2options API的同时还推出了composition API,大大增加了代码的逻辑组织和代码复用能力

这里代码简单演示下:

存在一个获取鼠标位置的函数

import { toRefs, reactive } from 'vue'
function useMouse() {
  const state = reactive({ x: 0, y: 0 })
  const update = (e) => {
    state.x = e.pageX
    state.y = e.pageY
  }
  onMounted(() => {
    window.addEventListener('mousemove', update)
  })
  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })

  return toRefs(state)
}

        我们只需要调用这个函数,即可获取xy的坐标,完全不用关注实现过程

        试想一下,如果很多类似的第三方库,我们只需要调用即可,不必关注实现过程,开发效率大大提高

        同时,VUE3是基于typescipt编写的,可以享受到自动的类型定义提示

 三、优化方案

vue3从很多层面都做了优化,可以分成三个方面:

  • 源码
  • 性能
  • 语法 API

 源码

源码可以从两个层面展开:

  • 源码管理
  • TypeScript
 源码管理

  vue3整个源码是通过 monorepo的方式维护的,根据功能将不同的模块拆分到packages目录下面不同的子目录中

        这样使得模块拆分更细化,职责划分更明确,模块之间的依赖关系也更加明确,开发人员也更容易阅读、理解和更改所有模块源码,提高代码的可维护性

        另外一些 package(比如 reactivity 响应式库)是可以独立于 Vue 使用的,这样用户如果只想使用 Vue3的响应式能力,可以单独依赖这个响应式库而不用去依赖整个 Vue

 TypeScript

   Vue3是基于typeScript编写的,提供了更好的类型检查,能支持复杂的类型推导

 性能

   vue3是从什么哪些方面对性能进行进一步优化呢?

  • 体积优化
  • 编译优化
  • 数据劫持优化

这里讲述数据劫持:

        在vue2中,数据劫持是通过Object.defineProperty,这个 API 有一些缺陷,并不能检测对象属性的添加和删除

Object.defineProperty(data, 'a', {
  get() {
    // track
  },
  set() {
    // trigger
  },
})

        尽管Vue为了解决这个问题提供了 setdelete实例方法,但是对于用户来说,还是增加了一定的心智负担

        同时在面对嵌套层级比较深的情况下,就存在性能问题

default {
  data: {
    a: {
      b: {
          c: {
          d: 1
        }
      }
    }
  }
}

        相比之下,vue3是通过proxy监听整个对象,那么对于删除还是监听当然也能监听到

        同时Proxy 并不能监听到内部深层次的对象变化,而 Vue3 的处理方式是在getter 中去递归响应式,这样的好处是真正访问到的内部对象才会变成响应式,而不是无脑递归

 语法 API

         这里当然说的就是composition API,其两大显著的优化:

  • 优化逻辑组织
  • 优化逻辑复用
 逻辑组织

一张图,我们可以很直观地感受到 Composition API在逻辑组织方面的优势

相同功能的代码编写在一块,而不像options API那样,各个功能的代码混成一块

 逻辑复用

        在vue2中,我们是通过mixin实现功能混合,如果多个mixin混合,会存在两个非常明显的问题:命名冲突和数据来源不清晰

        而通过composition这种形式,可以将一些复用的代码抽离出来作为一个函数,只要的使用的地方直接进行调用即可

        同样是上文的获取鼠标位置的例子

import { toRefs, reactive, onUnmounted, onMounted } from 'vue'
function useMouse() {
  const state = reactive({ x: 0, y: 0 })
  const update = (e) => {
    state.x = e.pageX
    state.y = e.pageY
  }
  onMounted(() => {
    window.addEventListener('mousemove', update)
  })
  onUnmounted(() => {
    window.removeEventListener('mousemove', update)
  })

  return toRefs(state)
}

组件使用

import useMousePosition from './mouse'
export default {
  setup() {
    const { x, y } = useMousePosition()
    return { x, y }
  },
}

        可以看到,整个数据来源清晰了,即使去编写更多的hook函数,也不会出现命名冲突的问题

  • https://juejin.cn/post/6850418112878575629#heading-5
  • https://vue3js.cn/docs/zh

 参考文献

  • https://juejin.cn/post/6850418112878575629#heading-5

  • https://vue3js.cn/docs/zh

  • https://vue3js.cn/docs/zh/guide/migration/introduction.html#%E6%A8%A1%E6%9D%BF%E6%8C%87%E4%BB%A4

  • https://composition-api.vuejs.org/zh/#api-%E4%BB%8B%E7%BB%8D

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值