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
是一个不错的选择,因为它会在初始化时立即执行,且后续数据变化时也会响应。