Vue.js 2.x 的源码托管在 src 目录,而后依据功能拆分出了 compiler(模板编译的相关代码)、core(与平台无关的通用运行时代码)、platforms(平台专有代码)、server(服务端渲染的相关代码)、sfc(.vue 单文件解析相关代码)、shared(共享工具代码)等目录。vue
Vue.js 3.0,整个源码是经过 monorepo 的方式维护的,根据功能将不一样的模块拆分到 packages 目录下面不一样的子目录中,每一个 package 有各自的 API、类型定义和测试。node
Vue.js 2.x 选用 Flow 作类型检查,来避免一些因类型问题致使的错误,可是 Flow 对于一些复杂场景类型的检查,支持得并很差。算法
Vue.js 3.0 抛弃了 Flow ,使用 TypeScript 重构了整个项目。 TypeScript 提供了更好的类型检查,能支持复杂的类型推导;因为源码就使用 TypeScript 编写,也省去了单独维护 d.ts 文件的麻烦。typescript
Vue.js 2.x 内部是经过 Object.defineProperty 这个 API 去劫持数据的 getter 和 setter 来实现响应式的。这个 API 有一些缺陷,它必须预先知道要拦截的 key 是什么,因此它并不能检测对象属性的添加和删除。api
Vue.js 3.0 使用了 Proxy API 作数据劫持,它劫持的是整个对象,天然对于对象的属性的增长和删除都能检测到。性能优化
在 Vue.js 2.x 中,对于一个深层属性嵌套的对象,要劫持它内部深层次的变化,就须要递归遍历这个对象,执行 Object.defineProperty 把每一层对象数据都变成响应式的,这无疑会有很大的性能消耗。函数
在 Vue.js 3.0 中,使用 Proxy API 并不能监听到对象内部深层次的属性变化,所以它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的能够说是按需实现响应式,就没有那么大的性能消耗。工具
Vue.js 2.x 的数据更新并触发从新渲染的粒度是组件级的,单个组件内部须要遍历该组件的整个 vnode 树。性能
Vue.js 3.0 作到了经过编译阶段对静态模板的分析,编译生成了 Block tree。Block tree 是一个将模版基于动态节点指令切割的嵌套区块,每一个区块内部的节点结构是固定的。每一个区块只须要追踪自身包含的动态节点。测试
Vue.js 2.x 中,若是有一个组件传入了slot,那么每次父组件更新的时候,会强制使子组件update,形成性能的浪费。
Vue.js 3.0 优化了slot的生成,使得非动态slot中属性的更新只会触发子组件的更新。动态slot指的是在slot上面使用v-if,v-for,动态slot名字等会致使slot产生运行时动态变化可是又没法被子组件track的操做。
使用 Vue.js 2.x 编写组件本质就是在编写一个“包含了描述组件选项的对象”,能够把它称为 Options API。咱们按照 data、props、methods、computed 这些不一样的选项来书写对应的代码。这种方式对于小型的组件可能代码还能一目了然,但对于大型组件要修改一个逻辑点,可能就须要在单个文件中不断上下切换和寻找逻辑代码。
Vue.js 3.0 提供了一种新的 API:Composition API,它有一个很好的机制去解决这样的问题,就是将某个逻辑关注点相关的代码全都放在一个函数里,这样在修改一个逻辑时,只须要改那一块的代码了。
在 Vue.js 2.x 中,咱们通常会用 mixins 去复用逻辑。当抽离并引用了大量的mixins,你就会发现两个不可避免的问题:命名冲突和数据来源不清晰。
Vue.js 3.0 设计的 Composition API,在逻辑复用方面就会颇有优点了。