> 文章列表 > 2023 面试题vue2、vue3篇

2023 面试题vue2、vue3篇

2023 面试题vue2、vue3篇

vue2和vue3的区别

API模式不同

Vue2与Vue3 最大的区别:Vue2使用选项式API(Options API)对比Vue3组合式API(Composition API)

监测机制的改变

vue3 中使用了ES6 的 ProxyAPI 对数据代理,监测的是整个对象,而不再是某个属性。

  • 消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制
  • vue3可以监测到对象属性的添加和删除,可以监听数组的变化;
  • vue3支持 Map、Set、WeakMap 和 WeakSet。

建立数据的方式不同

  • Vue2:这里把数据放入data属性中
  • Vue3:需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。

生命周期钩子不同

  • setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
  • onBeforeMount() : 组件挂载到节点上之前执行的函数。
  • onMounted() : 组件挂载完成后执行的函数。
  • onBeforeUpdate(): 组件更新之前执行的函数。
  • onUpdated(): 组件更新完成之后执行的函数。
  • onBeforeUnmount(): 组件卸载之前执行的函数
  • onUnmounted(): 组件卸载完成后执行的函数

若组件被包含,则多出下面两个钩子函

  • onActivated(): 被包含在中的组件,会多出两个生命周期钩子函数。被激活时执行 。
  • onDeactivated(): 比如从 A组件,切换到 B 组件,A 组件消失时执行。

父子传参不同

子组件通过defineProps()进行接收,并且接收这个函数的返回值进行数据操作。
总结: vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便

defineProperty和proxy的区别

Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。并 劫持各个属性 getter 和 setter,在数据变化时发布消息给订阅者,触发相应的监听回调,而这之间存在几个问题

  • 初始化时需要遍历对象所有 key,如果对象层次较深,性能不好
  • 通知更新过程需要维护大量 dep 实例和 watcher 实例,额外占用内存较多
  • Object.defineProperty 无法监听到数组元素的变化,只能通过劫持重写数方法
  • 动态新增,删除对象属性无法拦截,只能用特定 set/delete API 代替
  • 不支持 Map、Set 等数据结构

Vue3 使用 Proxy 来监控数据的变化。Proxy 是 ES6 中提供的功能,其作用为:用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。相对于Object.defineProperty(),其有以下特点:

  • Proxy 直接代理整个对象而非对象属性,这样只需做一层代理就可以监听同级结构下的所有属性变化,包括新增属性和删除属性。
  • 它的处理方式是在 getter 中去递归响应式,这样的好处是真正访问到的内部属性才会变成响应式,简单的可以说是按需实现响应式,减少性能消耗。
  • Proxy 可以监听数组的变化。

什么是虚拟dom

简单描述:首次染会调用一次 patch 并创建新的vnode,不会进行更深层次的比较,然后是在组件中数据发生变化时会触发setter 通过 Notifv 通知 watcher 对应的watcher会通知更新并执行更新函数,它会执行 render 函数获取新的虚拟 DOM.然后执行patch 对比上次渲染结果的老的虚拟DOM,并计算出最小的变化,再根据这个最小的变化去更新真是DOM

什么是diff算法

diff的过程就是调用名为patch的函数,比较新旧节点,一边比较一边给真实的DOM打补丁

Vue3 Diff算法和 Vue2 的区别

我们知道在数据变更触发页面重新渲染,会生成虚拟 DOM 并进行 patch 过程,这一过程在 Vue3 中的优化有如下

编译阶段的优化:

  • 事件缓存:将事件缓存(如: @click),可以理解为变成静态的了
  • 静态提升:第一次创建静态节点时保存,后续直接复用
  • 添加静态标记:给节点添加静态标记,以优化 Diff 过程
    由于编译阶段的优化,除了能更快的生成虚拟 DOM 以外,还使得 Diff 时可以跳过"永远不会变化的节点",

Diff 优化如下

  • Vue2 是全量 Diff,Vue3 是静态标记 + 非全量 Diff
  • 使用最长递增子序列优化了对比流程

composition API 与 options API的区别

vue2 采用的就是 optionsAPI

  • 优点:易于学习和使用, 每个代码有着明确的位置 (例如: 数据放 data 中, 方法放 methods中)
  • 缺点: 相似的逻辑, 不容易复用, 在大项目中尤为明显
  • 虽然 optionsAPI 可以通过mixins 提取相同的逻辑, 但是也并不是特别好维护

vue3 新增的就是 compositionAPI

  • compositionAPI 是基于 逻辑功能 组织代码的, 一个功能 api 相关放到一起
  • 即使项目大了, 功能多了, 也能快速定位功能相关的 api
  • 大大的提升了 代码可读性 和 可维护性

vue3 推荐使用 composition API, 也保留了options API

即就算不用composition API, 用 vue2 的写法也完全兼容!!

setup 函数

setup() 函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3的 Composition API 新特性提供了统一的入口, setup 函数会在 beforeCreate 、created 之前执行, vue3也是取消了这两个钩子,统一用setup代替, 该函数相当于一个生命周期函数,vue中过去的data,methods,watch等全部都用对应的新增api写在setup()函数中。

setup() 接收两个参数 props 和 context。它里面不能使用 this,而是通过 context 对象来代替当前执行上下文绑定的对象,context 对象有四个属性:attrs、slots、emit、expose

Computed 和 Watch 的区别

  • computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值。
  • watch 侦听器 : 更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。

watch 和 watchEffect 的区别

watch 作用是对传入的某个或多个值的变化进行监听;触发时会返回新值和老值;也就是说第一次不会执行,只有变化时才会重新执行。
watchEffect 是传入一个函数,会立即执行,所以默认第一次也会执行一次;不需要传入监听内容,会自动收集函数内的数据源作为依赖,在依赖变化的时候又会重新执行该函数,如果没有依赖就不会执行;而且不会返回变化前后的新值和老值。
共同点是 watch 和 watchEffect 会共享以下四种行为:

  • 停止监听:组件卸载时都会自动停止监听
  • 清除副作用:onInvalidate 会作为回调的第三个参数传入
  • 副作用刷新时机:响应式系统会缓存副作用函数,并异步刷新,避免同一个 tick 中多个状态改变导致的重复调用
  • 监听器调试:开发模式下可以用 onTrack 和 onTrigger 进行调试

Vue3 的生命周期

基本上就是在 Vue2 生命周期钩子函数名基础上加了 on;beforeDestory 和 destoryed 更名为 onBeforeUnmount 和 onUnmounted;然后用setup代替了两个钩子函数 beforeCreate 和 created;新增了两个开发环境用于调试的钩子

Vite 和Webpack的区别

  • 启动方式不一样。vite在启动的时候不需要打包,所以不用分析模块与模块之间的依赖关系,不用进行编译。这种方式就类似于我们在使用某个UI框架的时候,可以对其进行按需加载。同样的,vite也是这种机制,当浏览器请求某个模块时,再根据需要对模块内容进行编译。按需动态编译可以缩减编译时间,当项目越复杂,模块越多的情况下,vite明显优于webpack.
  • 热更新方面,效率更高。当改动了某个模块的时候,也只用让浏览器重新请求该模块,不需要像webpack那样将模块以及模块依赖的模块全部编译一次。

Vue 响应式原理

响应式原理3个步骤:数据劫持、依赖收集、派发更新。

数据分为两类:对象、数组。

对象

遍历对象,通过Object.defineProperty为每个属性添加 getter 和 setter,进行数据劫持。getter 函数用于在数据读取时进行依赖收集,在对应的 dep 中存储所有的 watcher;setter 则是数据更新后通知所有的 watcher 进行更新。

数组

用数组增强的方式,覆盖原属性上默认的数组方法,保证在新增或删除数据时,通过 dep 通知所有的 watcher 进行更新。

组件中的 data 为什么是个函数

对象在栈中存储的都是地址,函数的作用就是属性私有化,保证组件修改自身属性时不会影响其他复用组件。

data用return返回

不使用return包裹的数据会在项目的全局可见,会造成变量污染;使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。

Vue.$nextTick 的原理

在下次 DOM 更新循环结束之后执行延迟回调。常用于修改数据后获取更新后的DOM。