Vue2到Vue3的优化总结

前言:我觉得这个面试的时候比较常问,我之前背这方面的面试题很费劲,因为是死记硬背,根本不懂里面的含义。但是了解Vue大部分源码的实现思路之后,一切都豁然开朗。

不得不说这种问题确实很难,因为我花了大量时间学习Vue原理才对下面的内容完全了解

源码层面的优化

源码优化面向的是框架的开发者,目的是让框架本身的代码更易于开发和维护。源码的优化主要体现在使用monorepo和TypeScript开发和管理源码.

Monorepo 是 "monolithic repository" 的缩写,意为"单一仓库"。它是一种代码管理策略,其中在单个版本控制仓库(如 Git 仓库)中存储多个项目或包。这些项目可能是相互关联的,或者是完全独立的。

优点:

  1. 可以更轻松地管理和更新仓库中所有项目的依赖
  2. 可以在单个仓库中构建和测试所有的项目或包,确保它们之间没有冲突

Vue2的源码统一放在src下,3则是放在package下。内部文件都是根据功能划分,但是3的功能划分力度更细致,每个项目之间没有影响,有着自己的API,类型定义和单元测试。

例如:你只想获得Vue提供的响应式能力,对于2来说,你不得不引入整个Vue.js.但是对于3来说,你可以只引用Vue下的reactivity响应库。

2用的是flow,3用的是typeScript。对于typeScript,我的理解是对于框架,组件库很有必要,因为有利于IDE自动补全,并且有更清晰的架构

性能优化

源码体积优化

因为包的大小减小,传输时间就会加快,解析包的速度也会加快

  1. 移除了部分API,例如过滤器
  2. 引入树摇减小打包体积。tree-shaking的原理也很简单:依赖ES2015模块语法的静态结构import,export,通过编译阶段的静态分析找到没有导人的模块并打上标记然后在压缩阶段利用压缩工具删除已标记的代码。内置组件例如keepAlive没有被使用就不会被打包进来。

数据劫持优化

对于2的Object.defineProperty

  1. 因为需要预先知道要拦截的key是什么,所以并不能检测对象属性的添加和删除
  2. 对于一个较深层级的对象来说,不管是否会访问到深层级的属性,都会进行深度监听,一次性计算量大

Vue.js3使用的proxy不会出现上面的第一个问题。虽然对于深层级对象,仍然需要递归实现,但是它是在proxy的getter操作中赋予响应式。意味着只有访问到这个层级的属性才会建立响应,而不是像2一样直接给整个对象都加上响应。

关于如何深度监听对象可以看我的这篇文章

渲染优化

从双端Diff算法升级为快速Diff算法,具体可以看我的这两篇文章

  1. 双端Diff算法
  2. 快速Diff算法

编译优化

通过数据劫持和依赖收集,Vue2数据更新并触发重新渲染的粒度是组件级的。

由于 Vue 使用了模板和组件的组合方式,每个组件都有自己独立的数据对象、依赖收集和渲染上下文。这意味着数据变化只会触发当前组件内部的重新渲染,不会影响其他组件,因此数据更新和重新渲染的粒度是组件级的。

但如果组件中有静态节点,即以后都不会发生改变,但是Diff算法还是会重新比较这些静态节点,尽管我们已经知道这些比较毫无意义。

Vue3在编译阶段对静态模板进行了分析,编译生成了BlockTree,它会指导Diff算法的执行跳过静态节点。。

组合式APi

这个是对于用户来说改变最大的部分,一种新的代码组织逻辑。但不是Vue的编程范式,他的出现不是为了取代选项式。

但它有着更好的代码逻辑复用能力,在选项式中通过mixin可以使用代码复用,但是使用它可能会导致数据来源不明确和命名冲突

因为不知道数据是从哪个mixin而来,不同mixin中函数名相同可能会产生意料之外的结果。例如我们要复用一个获取鼠标坐标的逻辑

js 复制代码
// useMousePosition.js
import { ref, onMounted, onBeforeUnmount } from 'vue';

export function useMousePosition() {
  const mouseX = ref(0);
  const mouseY = ref(0);

  function handleMouseMove(event) {
    mouseX.value = event.clientX;
    mouseY.value = event.clientY;
  }

  onMounted(() => {
    window.addEventListener('mousemove', handleMouseMove);
  });

  onBeforeUnmount(() => {
    window.removeEventListener('mousemove', handleMouseMove);
  });

  return {
    mouseX,
    mouseY,
  };
}
js 复制代码
<template>
  <div>
    <p>Mouse X: {{ mouseX }}</p>
    <p>Mouse Y: {{ mouseY }}</p>
  </div>
</template>

<script>
import { useMousePosition } from './useMousePosition';

export default {
  setup() {
    const { mouseX, mouseY } = useMousePosition();

    return {
      mouseX,
      mouseY,
    };
  },
};
</script>

这样整个的数据流向就很清晰了,并且函数可以接受参数也就更加灵活。多个自定义钩子函数又可以相互组合,而不必担心混合对象的复杂性和顺序问题

补充:

RFC

它记录着Vue新功能或功能废弃的讨论,通过它你可以了解到某一功能新增或取消的前因后果。 RfC文档

相关推荐
也无晴也无风雨36 分钟前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、4 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤5 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser6 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui