Proxy 取代 Object.defineProperty
-
Object.defineProperty 的限制:
- 在 Vue 2 中,响应式系统是通过 Object.defineProperty 实现的。它通过劫持对象属性的 getter 和 setter 来实现数据的响应式跟踪。
- 然而,Object.defineProperty 存在一些限制。它只能用于对象属性,而不能用于数组元素或对象的深层属性。
- 不用于数组,是从框架的性能和应用场景进行权衡考量,最终做出的取舍。作为一个数组类型,不可避免的会存在大量数据。为了实现对数组索引的劫持,就需要对数组中每一项进行观测,开销可能会比较大,如果数组中有 10000 条数据,那么将全部被添加 get、set 方法。
-
Proxy 的优点:
- Proxy 是 ES6 引入的一种强大的元编程特性,它提供了更灵活的方式来监听和拦截对象上的操作,包括属性的访问、修改、添加和删除。
- Proxy 可以用于对象和数组,使得响应式数据可以深层嵌套而不需要额外的处理
const data = {
array: [],
};
data.array = new Proxy(data.array, {
get(target, key) {
console.log(`read "array"`);
return target[key];
},
set(target, key, value) {
console.log(`set "array" 中的 "${key}" 为:`, value);
// 使用 Reflect.set 来确保数组的修改被正确处理
Reflect.set(target, key, value);
console.log('array 中的 "${key}" 为:', value);
return true;
},
});
data.array.push(1);
console.log(data.array);
性能提升
Vue 3 通过引入静态树提升、Patch Flag 和事件处理的优化等技术,显著提高了渲染性能。这意味着即使在具有大量数据和复杂模板的情况下,Vue 3 仍能更快地渲染和更新页面,
- 更快的渲染:
- 在 Vue 2 中,每次数据发生变化时,整个组件的 Virtual DOM 都会被重新构建。这意味着即使只有一个小的数据变化,整个组件的 Virtual DOM 都会被比对和重新渲染。
- Vue 3 引入了静态树提升(Static Tree Hoisting),可以将不变的部分从 Virtual DOM 中提取出来,以减少不必要的比对和渲染。这导致更快的渲染速度。
<template>
<div>
<p>{{ message }}</p>
<button @click="updateMessage">更新</button>
</div>
</template>
-
优化的事件处理:
- 在 Vue 2 中,事件处理函数在每次重新渲染时都会被重新创建,这可能会导致性能问题。
- Vue 3 使用了更高效的事件代理,使得事件处理函数只创建一次,而不是每次渲染都创建一次。
<template> <button @click="handleClick">点击我</button> </template> -
静态提升和 Patch Flag:
- Vue 3 使用 Patch Flag 标志来跟踪哪些部分的 Virtual DOM 需要更新,从而避免不必要的更新。
- 静态提升将静态部分的 Virtual DOM 从渲染中分离出来,进一步提高渲染性能。
<template> <div> <p>{{ message }}</p> <!-- 这里的数据是动态的 --> <button @click="updateMessage">更新</button> </div> </template>
Composition API
是 Vue3 的新特性,它允许将相关逻辑聚合在一起,解决了 Vue2 中 mixins 中存在的问题
- 不清晰的数据来源:当使用多个 mixins 时,确切知道数据属性来自哪个 mixin 变得困难
- 命名空间冲突:多个 mixin 可能会注册相同的属性名,导致命名冲突
- 隐式的跨 mixin 交流:多个 mixin 需要依赖共享的属性名进行相互作用,这使得它们隐式地耦合在一起
使用 Vue3 的 Composition API,可以通过使用 ref 和解构模式明确指定数据属性的来源,允许将属性明确命名,避免不同 mixin 之间的属性名冲突。可以将一个组合式函数的返回值作为另一个组合式函数的参数传递,从而更清晰地定义和管理依赖关系。
Teleport
将组件的内容渲染到 DOM 中的不同位置,对于创建模态框、对话框和弹出窗口等情况非常有用。
Suspense
用于处理异步数据加载和组件渲染的加载状态
Fragments
允许在组件中返回多个根元素,不需要包装它们在一个外围容器内
全面支持TypeScript
更好的类型推断和类型检查,这有助于减少潜在的运行时错误,提高了代码的可维护性。