Vue3 面试题小总结
1. OptionsAPI 与 CompositionAPI 的区别?
- OptionsAPI:
- 选项式API,通过定义
data、computed、watch、method
等属性与方法,共同处理页面逻辑; - 缺点:
- 当组件变得复杂的时候,导致对应属性的列表也会增长,可能会导致组件难以阅读和后期维护成本变高;
- 选项式API,通过定义
- CompositionAPI:
- 组合式API,组件根据逻辑功能来组织,一个功能所定义的所有API会放在一起(高内聚,低耦合);
- 优点:
- 内部的功能容易碎片化,像某一个功能相关的数据放在一块,容易阅读和维护(不用翻来翻去找);
- 将某个逻辑关注点相关的代码全都放在一个函数里,这样,当需要修改一个功能时,就不再需要在文件中跳来跳去;
- 逻辑复用:
- 在Vue2中,当混入多个
mixin
会存在两个非常明显的问题:命名冲突,数据来源不清晰; - 而组合式API可以通过编写多个函数就很好的解决了;
- 在Vue2中,当混入多个
- 总结:
- 在逻辑组织和逻辑复用这方面,组合式API是优于选项式API的;
- 组合式API中见不到this的使用,减少了this指向不明的情况;
- 组合式API几乎都是函数,会有更好的类型推断;
2. Vue3中为什么采用 Proxy 代替 defineProperty
- defineProperty:
- 来劫持整个对象,然后进行深度遍历,给每个属性添加
getter
和setter
,实现响应式,但是存在以下问题:- 检测不到对象属性的添加和删除;
- 数组API方法无法监听到;
- 需要对每个属性进行深度遍历,如果是嵌套对象,需要深层次监听,造成性能问题;
- 来劫持整个对象,然后进行深度遍历,给每个属性添加
- Proxy:
- 监听整个对象,那么整个对象的所有操作都会进入监听操作;
- 总结:
Object.
defineProperty只能遍历对象属性进行劫持;Proxy
直接可以劫持整个对象,便返回一个新对象,我们可以操作新对象达到响应式目的;Proxy
可以直接监听数组的变化;- Proxy有13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等,这是Object.defineProperty不具备的;
3. Vue3响应式原理
- Vue响应式使用的是ES6的
Proxy
和Reflect
相互配合实现数据响应式,解决了Vue2中试图不能自动更新的问题; Proxy
是深度监听,所以可以监听对象和数组内的任意元素,从而可以实现视图实时更新;- 响应式大致分为三个阶段:
- 初始化阶段:
- 初始化阶段通过组件初始化方法形成对应的
proxy
对象,然后形成一个负责渲染的effct
;
- 初始化阶段通过组件初始化方法形成对应的
- get依赖收集阶段:
- 通过解析
template
,替换真实data
属性,来触发get
,然后通过satck
方法,通过proxy对象
和key
形成对应的deps
,将负责渲染的effect
存入deps
。(这个过程还有其他的effect,比如watchEffect存入deps中 )。
- 通过解析
- set派发更新阶段:
- 当我们
this[key] = value
改变属性的时候,首先通过trigger
方法,通过proxy对象
和key
找到对应的deps
,然后给deps
分类分成computedRunners
和effect
,然后依次执行,如果需要调度
的,直接放入调度。
- 当我们
- 初始化阶段:
Proxy只会代理对象的第⼀层,那么Vue3⼜是怎样处理这个问题的呢?
- 判断当前Reflect.get的返回值是否为Object,如果是则再通过 reactive ⽅法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防⽌触发多次呢?
- 我们可以判断key是否为当前被代理对象target⾃身属性,也可以判断旧值与新值是否相等,只有满⾜以上两个条件之⼀时,才有可能执⾏trigger。
4. watch 和 watchEffect 的区别?
watch
和watchEffect
都是监听器,watchEffect
是一个副作用函数,它们之间的区别有:
watch
:既要指明监听数据的源,也要指明监听的回调;watchEffect
:可以自动监听数据源作为依赖,不用指明监听那个数据,监听的回调中用到哪个数据,那就监听哪个数据;watch
可以访问改变前后的值,watchEffect
只能获取改变后的值;watch
运行的时候 不会立即执行,值改变后才会执行,而watchEffect
运行后可立即执行,这一点可以通过watch
的配置项immeriate
改变;watchEffect
有点像computed
:computed
注重的是计算出来的值(回调函数的返回值),所以必须写返回值;watchEffect
注重的是过程(回调函数的函数体),所以不用写返回值;watchEffect
所指定的回调中用到的数据只要发生变化,则直接重新执行回调;
- Vue3与Vue2中的watch配置项一致,但也有两个小坑:
- 监听
reactive
定义的响应式数据时,oldVal
无法正确获取到,强制开启深度监听,depp配置项失效; - 监听
reactive
定义的响应式数据的某个属性时,deep配置项有效;
- 监听
5. ref 与 reactive 的区别?
ref
与reactiv
e它们主要用于响应式数据的创建;ref
函数可以接收原始数据类型和引用数据类型;- 使用
ref
声明的数据,在JS中使用的时候,需要添加.value
的后缀; reactive
函数只能接收引用数据类型;ref
底层还是使用reactive
来做,ref
是在reactive
上进行了封装,增强了其能力,使其支持了对原始数据类型的处理;- Vue3中,
reactive
能做的ref
能做,reactive
不能做的ref
也能做;
6. script setup 是干什么的?
script setup
是Vue3的语法糖,简化了组合式API的写法,并且运行性能更高,使用script setup
语法糖的特点:
- 属性和方法无需返回,直接使用;
- 引入组件的时候,会自动注册;
- 使用
defineProps
接收父组件传递的值; - 使用
useAttrs
获取属性,useSlots
获取插槽,defineEmits
获取自定义事件; - 默认不会对外暴露任何属性,如果有需要使用
defineExpose
;
7. vFor 与 vIf 的优先级
- 当面试官问到这个问题的时候,我们不能直接说前者比后者高(或者后者比前者高);
- 我们应当根据Vue的不同版本做不同的回答;
- Vue2:
vFor
高于vIf
;
- Vue3:
vIf
高于vFor
;
- 两个版本的区别:
Vue2
中,可以一起使用,但是非常不推荐哈,vIf
也能获取到vFor
中的item
;Vue3
中,不能一起使用,因为vIf
不能使用vFor
中的item
(会直接报错,不能从undefined
中读取xxx
属性);