1. vue3移除了哪些特性?
a. 移除的特性
inline-template语法
Vue 2 允许在组件标签内直接编写模板代码(如<component inline-template>...</component>),但这种方式破坏了模板作用域的清晰性,且难以维护。Vue 3 彻底移除了此语法,强制使用<template>标签或单文件组件(SFC)的模板定义。- 过滤器(
filter)
Vue 2 中通过{{ value | filterName }}实现的过滤器功能被移除,主要原因是其功能与计算属性或方法重叠,且增加了模板解析的复杂性。替代方案:
-
- 计算属性:用于同步数据转换。
- 方法调用:如
{{ formatValue(value) }}。 - 全局工具函数:通过
app.config.globalProperties注册通用函数。
$children实例属性
Vue 2 中通过this.$children访问子组件实例的方式被移除,因其易导致组件间隐式耦合。替代方案:
-
ref****和 ****$refs:显式标记需访问的子组件。provide/inject:跨层级组件通信。
- 事件 API(
$on、$off、$once)
原先用于全局事件总线的$on、$off、$once方法被移除,因其在大型应用中难以维护事件流。替代方案:
-
- 第三方库:如
mitt或tiny-emitter。 - 组合式函数:封装自定义事件逻辑。
- 第三方库:如
- 按键修饰符的别名
Vue 2 支持的@keyup.enter等别名(如@keyup.13)被移除,统一使用按键名(如@keyup.enter)。
b. 其他调整与弃用
$destroy****方法
手动调用this.$destroy()销毁组件实例的方式不再推荐,Vue 3 的响应式系统会自动管理生命周期。Vue.extend****的简化
Vue 3 更推荐使用defineComponent函数定义组件,增强 TypeScript 支持并统一代码风格。Vue.config部分配置项
如Vue.config.productionTip(生产环境提示)和Vue.config.ignoredElements(忽略元素)被移除或调整。
2. 请问vue3做了哪些优化?
a. 性能优化
- 响应式系统升级:
-
- 使用 Proxy 替代 Object.defineProperty:Vue 3 使用 ES6 的
Proxy来实现数据劫持,相较于 Vue 2 基于Object.defineProperty的方式,Proxy能直接代理整个对象,而非单个属性。这不仅可以检测对象属性的新增和删除,还能全面检测数组变化,无需像 Vue 2 那样使用特殊 API(如Vue.set和Vue.delete)。例如,在 Vue 3 中直接对对象新增属性就能被响应式系统捕获,而 Vue 2 则无法直接检测到。 - 更高效的依赖跟踪:Vue 3 引入了更细粒度的依赖跟踪机制。通过
effect、track和trigger函数,精确控制依赖收集和更新触发,减少不必要的更新。例如,当一个复杂对象中有多个属性,只有被访问和依赖的属性变化时,才会触发相关副作用函数的执行,提升了更新的精准性。
- 使用 Proxy 替代 Object.defineProperty:Vue 3 使用 ES6 的
- 编译优化:
-
- 静态提升:Vue 3 编译器会将模板中的静态节点(在组件渲染过程中不会发生变化的节点)提升到渲染函数外部,仅在初始渲染时创建一次,后续渲染不再重复创建,减少渲染开销。例如,模板中的静态文本、不依赖响应式数据的元素等,都会被提升。
- 预字符串化:对于简单的静态节点,Vue 3 编译器直接将其编译为字符串,而不是生成创建节点的代码,减少运行时创建节点的开销。例如,简单的静态
<div>元素,编译后直接以字符串形式存在,渲染时直接插入。 - 缓存事件处理函数:对于模板中绑定的无响应式依赖的普通事件处理函数,Vue 3 编译器会进行缓存,多次渲染时复用相同的函数实例,减少内存开销。
b. 功能增强
- 更好的 TypeScript 支持:Vue 3 从设计上对 TypeScript 提供了更友好的支持。
setup函数的使用使得在组件中使用 TypeScript 更加自然,类型推导更准确。例如,在setup函数中定义的数据和函数,TypeScript 能更好地推断其类型,减少类型声明的冗余,提高代码的可维护性和健壮性。 - 片段(Fragments)支持:Vue 3 允许模板中使用片段,即可以有多个根节点而无需额外的包装元素。这在一些场景下更加灵活,比如在
v - for循环中直接返回多个元素,渲染时不会额外创建不必要的 DOM 节点,提升性能的同时简化了模板结构。
c. API 优化
- 全新的
setup函数:setup函数是 Vue 3 组件的新入口点,在组件创建之前执行,用于初始化组件的响应式数据、计算属性、方法等。它将数据和逻辑组织在一个函数内,使代码结构更清晰,逻辑更集中。 - 精简全局 API:Vue 3 对全局 API 进行了调整和精简,将一些全局配置和方法移动到应用实例上,使应用的全局配置和实例配置更加清晰。例如,在 Vue 2 中
Vue.use、Vue.mixin等方法直接在全局Vue对象上调用,而在 Vue 3 中通过createApp创建应用实例后,在实例上调用这些方法,增强了代码的模块化和可维护性。
d. 内存管理优化
- 减少内存泄漏风险:Vue 3 在组件销毁时,对事件监听、定时器等资源的清理更加彻底,减少了因资源未正确释放导致的内存泄漏风险。例如,在组件内部使用
addEventListener添加的事件监听器,在组件销毁时会自动移除,开发者无需手动处理,提高了代码的可靠性。
3. vue3为什么会使用proxy?
a. 更强大的对象劫持能力
- 深度监听:
Proxy可以直接代理整个对象,能够深度监听对象内部嵌套对象的变化。相比之下,Vue 2 使用Object.defineProperty只能对对象的属性进行逐个劫持,对于深层次嵌套的对象,需要递归遍历进行劫持,操作繁琐且性能消耗较大。
b. 更优的性能表现
- 初始化性能:在处理大型对象时,Vue 2 使用
Object.defineProperty对每个属性进行遍历并定义getter和setter,这在对象属性较多时会带来较大的性能开销。而Proxy只需对整个对象进行一次代理,无需逐个处理属性,大大减少了初始化时的性能消耗。 - 运行时性能:
Proxy的依赖收集和更新通知机制更加高效。Proxy可以精确控制对对象的各种操作(如属性访问、赋值、枚举等),使得依赖跟踪更加精准,能够更准确地触发更新,避免了不必要的重新渲染,提升了运行时的性能。
c. 更好的代码可维护性与扩展性
- 简洁的代码结构:使用
Proxy实现响应式系统,代码结构更加简洁清晰。相比于 Vue 2 中复杂的递归劫持和依赖收集逻辑,Vue 3 基于Proxy的实现代码量减少,逻辑更加直观,更易于理解和维护。 - 易于扩展功能:
Proxy提供了丰富的拦截操作(如get、set、has、deleteProperty等),这使得在扩展响应式系统功能时更加方便。例如,可以方便地在拦截操作中添加日志记录、权限控制等功能,而不需要对底层的响应式机制进行大规模修改。
4. vue3中watch和watchEffect有什么不同?
a. 监听数据的方式
watch:
- 显式指定监听源:
watch需要明确指定要监听的数据来源,可以是一个响应式数据(如ref、reactive创建的数据)、一个计算属性或返回一个值的函数。 - 支持深度监听:对于对象或数组类型的响应式数据,通过设置
deep: true选项,可以实现深度监听,即对象内部属性或数组元素变化时也能触发回调。
watchEffect:
- 自动追踪依赖:
watchEffect不需要显式指定监听源,它会自动追踪回调函数中使用的响应式数据。只要回调函数中使用的响应式数据发生变化,就会触发该回调 - 深度监听特性:由于它自动追踪所有依赖,对于对象和数组类型的数据,默认就是深度监听,无需像
watch那样手动设置deep选项。
b. 旧值访问能力
watch
回调函数可获取旧值 oldValue 和新值 newValue,适合需对比状态变化的场景(如日志记录、回滚操作)。
watchEffect
仅能访问当前最新值,无法直接获取旧值。
c. 初始执行时机
watch
默认不立即执行回调,需通过 immediate: true 强制首次触发。
适用场景:延迟执行逻辑(如避免组件初始化时立即请求接口)。
watchEffect
立即执行回调函数,类似 watch 的 immediate: true 模式。
d. 使用场景
watch:
- 特定数据变化响应:适用于需要精确控制监听特定数据变化,并根据新值和旧值进行特定处理的场景。比如在表单验证中,当某个输入框的值变化时,根据新旧值判断是否满足特定规则。
- 避免不必要的计算:当只关心特定数据的变化,且希望避免因其他无关数据变化导致的不必要计算时,
watch更合适,因为它可以明确指定监听源。
watchEffect:
- 自动响应副作用:适用于处理与响应式数据相关的副作用,如自动更新 DOM、发送网络请求等。由于它自动追踪依赖,无需手动指定监听源,代码更加简洁。
- 初始化及数据变化响应:如果需要在组件初始化时执行一次操作,并且在相关数据变化时再次执行,
watchEffect是一个不错的选择,因为它会在初始化时立即执行,且后续数据变化时也会响应。