1.生命周期
大部分生命周期钩子名称上+“on”关键字,功能是类似的。
不过vue3在组合式api种使用生命周期钩子时候需要先引入、而vue2在选项api种可以直接调用生命周期钩子。
setup是围绕beforeCreate和created生命周期钩子运行的,不需要显示的去定义。
2.书写方式:
在 Vue 2 中,使用 Options API 来定义组件的数据、方法等。
在 Vue 3 中,可以使用 组合式API 来组织组件的逻辑,可以使用 ref,reactive创建响应式数据,并在setup中书写组件逻辑。
而在 Vue 2 中,需要使用 data函数来定义响应式数据。
Vue2 的(Options API),一个逻辑会散乱在文件不同位置(data、props、computed、watch、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。
Vue3 的组合式API,可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。
而Compositon API正是解决上述问题,将某个逻辑关注点相关的代码全都放在一个函数里,
这样当需要修改一个功能时,就不再需要在文件中跳来跳去
下面举个简单例子,将处理count属性相关的代码放在同一个函数了
function useCount() {
let count = ref(10);
let double = computed(() => {
return count.value * 2;
});
const handleConut = () => {
count.value = count.value * 2;
};
console.log(count);
return {
count,
double,
handleConut,
};
}
组件上中使用count
export default defineComponent({
setup() {
const { count, double, handleConut } = useCount();
return {
count,
double,
handleConut
}
},
});
逻辑复用
在Vue2
中,我们是用过mixin
去复用相同的逻辑
使用单个mixin
似乎问题不大,但是当我们一个组件混入大量不同的 mixins
的时候
会存在两个非常明显的问题:
- 命名冲突
- 数据来源不清晰
现在通过Composition API
这种方式改写vue2的代码
3.虚拟dom:
Vue3 相比于 Vue2,虚拟dom增加了patchFlag 帮助 diff 的时侯区分静态节点,以及不同类型的动态节点。一定程度地减少节点本身及其属性的比对。
4.diff:
vue3
在diff
算法中相比vue2
增加了静态标记:不比较不重新渲染
告诉 Vue 哪些节点在多次渲染中是不会改变的,因此在更新时可以跳过对这些静态节点的比较和重新渲染,从而提高渲染性能。
比如:已经标记静态节点的p
标签在diff
过程中则不会比较,把性能进一步提高
静态提升:
Vue3
中对不参与更新的元素,即所有的静态节点(HOISTED 为 -1),都保存为一个变量进行静态提升,可在重新渲染时直接引用,无需重新创建。
这大型应用会受益于这个改动,免去了重复的创建操作,优化了运行时候的内存占用
5.composition api:
Vue2 是选项API(Options API),一个逻辑会散乱在文件不同位置(data、props、computed、watch、生命周期钩子等),导致代码的可读性变差。当需要修改某个逻辑时,需要上下来回跳转文件位置。
Vue3 组合式API,可将同一逻辑的内容写到一起,增强了代码的可读性、内聚性,其还提供了较为完美的逻辑复用性方案。
6.响应式原理
vue2
中采用 defineProperty
来劫持整个对象,然后进行深度遍历所有属性,给每个属性添加getter
和setter
,实现响应式
基本用法:直接在一个对象上定义新的属性或修改现有的属性,并返回对象。
vue3
采用proxy
重写了响应式系统,因为proxy
可以对整个对象进行监听,所以不需要深度遍历
-
可以监听动态属性的添加,删除
-
可以监听到数组的索引和数组
length
属性 -
Proxy 是 ES6 新特性,通过第2个参数 handler 拦截目标对象的行为。相较于 Object.defineProperty 提供语言全范围的响应能力,消除了vue2 的检测不了数组随想新增删除的局限性。
-
局限性:
-
Vue 的响应式原理虽然强大,但也存在一些潜在的缺陷和限制,其中一些包括:
1. Vue2 只能监听已经存在于数据对象中的属性,而无法检测对象属性的添加或删除。这意味着如果你在已经创建的对象上添加新的属性,Vue 不会触发视图更新。为了解决这个问题,可以使用 Vue.set() 或 this.$set() 方法来添加新属性。
-
2.数组变更的限制: Vue 对数组的响应式处理有一些限制。例如,直接通过索引修改数组元素或修改数组长度时,Vue 无法触发视图更新。需要使用特定的数组变异方法(如 push()、pop()、splice() 等)来确保 Vue 能够监听到数组的变化。
-
增加:pusc (push unshift splice concat) 前三个修改原数组
-
删除:psss(pop shift splice slice) 前三个修改原数组
-
数组变异方法:因为它们会直接修改原始数组,而不会创建新的数组副本。
7.ts支持:
Vue3 由 TypeScript 重写,
-
Vue2 Options API 中 option 是个简单对象,而 TypeScript 是一种类型系统,面向对象的语法,不是特别匹配。
-
Vue2 需要vue-class-component强化vue原生组件,也需要vue-property-decorator增加更多结合Vue特性的装饰器,写法比较繁琐。
8.体积更小:
vue3通过webpack
的tree-shaking
功能,将全局 API 进行分块。可以把没有用的模块“剪辑”掉,只去打包需要的模块。如果不使用他们某些功能,它们将不会包含在基础包中。
简单来讲,就是在保持代码运行结果不变的前提下,去除无用的代码。
也就是说 ,tree shaking
其实是找出使用的代码
在Vue2
中,无论我们使用什么功能,它们最终都会出现在生产代码中。主要原因是Vue
实例在项目中是单例模式的,捆绑程序无法检测到该对象的哪些属性在代码中被用。
在单例模式下,对象实例在运行时才会被创建,而不是在编译时。因此,打包工具在编译时无法静态分析实例的属性被实际使用情况。
9.Fragment(片段)
可以让你在 Vue 组件中返回多个根节点的机制。
在 HTML 中,每个元素都必须有一个根节点,但是有时候在 Vue 组件中,你希望返回多个相邻的节点而不需要包裹它们在一个额外的父节点内。
额外的父节点会增加 DOM 树的层级,可能会影响页面的性能和渲染速度。
·在 Vue 2 中,这是不允许的,但是在 Vue 3 中引入了 Fragment,解决了这个问题。
它本身不会创建额外的 DOM 节点。相反,它只是作为一个占位符存在,不会增加额外的 DOM 层级。