Vue 面试题

Vue 面试题

MVVM软件架构设计模式

  • 定义:MVVMModel-View-ViewModel 的缩写,它是一种用于构建用户界面的软件架构设计模式
  • 它的核心目标是 “实现数据与视图的自动同步”,从而让开发者从繁琐的 DOM 操作中解放出来,更加专注于数据和业务逻辑。
  • 核心机制:数据驱动视图,数据与视图的双向绑定

vue首屏优化方案

硬件方面

  1. 增加网络带宽
  2. cdn加速 服务器就近部署

软件方面

  1. 路由懒加载
  2. 静态资源压缩
  3. 拆包 懒加载部分资源

Vue 2Vue 3的核心区别

核心区别可以概括为“底层重构”和“上层创新”。

底层重构

  • 响应式系统重写:从Object.definePropertyProxy,解决了数组索引、长度修改、对象属性增删的监听问题,性能也更优。

上层创新

  • Composition API(组合式API):这是最大的范式转变。Options API(声明式 API) 在逻辑简单时很清晰,但逻辑复杂后,同一功能相关的代码(数据、方法、计算属性、生命周期)会分散在各处。Composition API 通过纯函数(setup<script setup> )将相关逻辑组织在一起,极大地提升了复杂逻辑的可读性、可复用性和可测试性。自定义组合函数(composables)是代码复用的利器。

refretive的区别

refreactive 都是创建响应式数据的核心 API,但设计目的和使用场景不同:

  1. 数据类型ref 可以包装任何类型,而 reactive 只处理对象类型。
  2. 访问方式ref 需要通过 .value 访问(模板中自动解包),reactive 直接访问属性。
  3. 重新赋值ref.value 可以被完全替换且保持响应性,而 reactive 直接重新赋值会丢失响应性

适用场景

  • ref:更适合原始值、可能被替换的数据、组合式函数返回值。
  • reactive:更适合需要深度响应式的复杂对象、相关状态的分组管理。

ref为什么要.value

ref 需要 .valueVue 3 响应式系统设计中一个深思熟虑的权衡

  • 技术层面:它是解决 JavaScript原始值无法被直接代理(修改)的唯一方案。通过创建包装对象,**Vue获得了追踪变化的能力 **。
  • 设计层面.value 作为 ref 容器的统一访问接口,保证了 API 的一致性,并明确区分了 ref(有 .value)和 reactive(直接访问属性)的使用场景。
  • 体验层面Vue 通过模板编译时的自动解包,消除了模板中的 .value ,让开发者获得近乎直接的编程体验,同时在脚本逻辑中保留 .value 以维持明确性和类型安全。

ref 能在全局替换时保持响应式,而 reactive 不能

根本原因在于两者的响应式实现层级不同

ref 是容器级的响应式

  • 它创建一个固定的包装对象,响应式系统追踪的是这个包装对象的 .value 属性。
  • 当你替换 .value 时,包装对象本身没变,响应式连接保持不变。
  • 新值如果是对象,会被自动转换为响应式。

reactive 是对象属性级的响应式

  • 它创建原始对象的 Proxy 代理,响应式系统追踪的是原始对象的具体属性。
  • 当你直接给 reactive 变量赋新值时,实际上是把变量指向了新对象,原来的 Proxy 代理丢失了,响应式连接也就断了。

设计差异

  • ref 采用 "盒模型":盒子固定,内容可换
  • reactive 采用 "包装纸模型":包装纸和对象绑定,换对象就没了包装纸

手写一个 ref 的实现

  1. 包装器模式ref 本质上是一个包装对象,通过 .value 属性来访问内部值。
  2. 依赖收集:在 getter 中收集当前正在执行的副作用(effect),建立响应式依赖关系。
  3. 触发更新:在 setter 中比较新旧值,如果不同,则触发所有收集到的依赖重新执行。
  4. 对象处理:如果内部值是对象,需要递归或代理使其也具有响应式。
  5. 标志位:通过 __v_isRef 等标志位让系统能够识别这是一个 ref 对象,从而实现模板中的自动解包等特性。

如何在计算属性中请求接口

Vue 3 中,不建议在计算属性中直接请求接口,因为计算属性的核心设计是同步的、无副作用的纯函数总结:在计算属性中请求的接口请求的数据不是实际的数据 是Promise对象 而且在网络请求时不能立即更新

计算属性的设计原则:

  1. 纯函数:相同的输入应该产生相同的输出,不应该有副作用(如网络请求、DOM 操作等)。

  2. 同步返回:计算属性必须立即返回计算结果,不能返回 Promise

  3. 缓存机制:基于依赖的缓存是其核心特性。

正确的解决 使用 watch + ref(最常用)

通过watch监听数据变化,并在其中进行网络请求,请求完毕后将结果赋值到ref中.

如何使监听器只监听一次

最新推荐(Vue 3.4+)

使用 watchonce: true 选项:

watch(source, callback, { once: true })

通用方法(所有 Vue 3 版本)

const stop = watch(source, (...args) => {
	callback(...args)
	stop() // 在回调中立即停止
})

watch和计算属性的区别

计算属性 (computed) 和监听器 (watch) 在 Vue 中是两个根本不同的概念,它们的核心区别在于:

设计目的不同:

  • computed 用于派生数据:基于现有响应式数据计算出一个新值
  • watch 用于监听数据源的变化,执行特定操作或副作用

缓存机制不同

  • computed 有强缓存:依赖不变时直接返回缓存值,避免重复计算
  • watch 无缓存:每次数据源变化时都执行回调

异步支持不同

  • computed 必须是同步操作,不能包含异步代码
  • watch 可以包含异步代码,如网络请求

返回值不同

  • computed 返回一个 ref 对象,可以访问内部值
  • watch 返回一个取消监听的函数,用于停止监听

简单记忆

  • computed:回答"是什么"的问题(这个值是什么?)

  • watch:回答"做什么"的问题(当这个变化时,要做什么?)

watchwatchEffect的区别

特性watchwatchEffect
设计目的监听特定数据源的变化,执行副作用自动追踪依赖变化,执行副作用
依赖收集显式声明要监听的数据源自动收集回调中用到的响应式依赖
执行时机默认惰性,数据变化时才执行(可配置 immediate)立即执行,并在依赖变化时重新执行
访问新旧值✅ 可以获取变化前后的值❌ 只能获取当前值,不知道具体哪个依赖变了
性能优化可以精确控制监听范围自动追踪,可能追踪到不需要的依赖
代码风格声明式、精确控制命令式、自动化

Vitewebpack的区别

ViteWebpack 都是优秀的构建工具,但它们的设计理念和适用场景有本质区别:

Webpack:全能但复杂

  • 核心理念:『打包一切』,预先构建完整的依赖图和bundle
  • 优势:功能极其全面,插件生态丰富,适合复杂、定制化要求高的大型项目
  • 劣势:随着项目规模增大,开发体验急剧下降(启动慢、热更新慢)

Vite:快速而现代

  • 核心理念:『按需编译』,利用浏览器原生ES模块,需要什么编译什么
  • 优势:开发体验极佳(秒级启动、毫秒级热更新),配置简单,面向现代浏览器
  • 劣势:插件生态相对较新,对老旧浏览器支持需要额外配置

关键技术差异:

  1. 开发服务器:Webpack 先打包后服务,Vite 直接服务按需编译
  2. 热更新:Webpack 重新打包依赖链,Vite 只更新单个文件
  3. 生产构建:Webpack 自研打包器,Vite 使用 Rollup
  4. 配置复杂度:Webpack 配置复杂但灵活,Vite 配置简单但约定优先
上次更新 2026/2/3 23:02:02