页面渲染优化
- 从回流的角度:html 不要嵌套过深,减轻回流的压力
- css 尽量使用精确的选择器(id和类名)减轻回流的压力
- 代码压缩(减轻请求的压力)
- js 线程不能和渲染线程同时工作,async 异步加载,defer 异步加载且延迟加载
- js 代码压缩
- 图片(懒加载,预加载,骨架屏,压缩,精灵图)
- 缓存
谈谈你对 vue 的理解
- vue 是一个渐进式的单页应用框架(页面上只有一个html文件,靠组件和路由来切页面,在开发时需要什么就开发什么)
- MVVM 数据驱动(model view viewModel):以数据来驱动页面更新,只要写模板代码,不需要去操作dom
- 组件化:提高代码的复用性,便于维护
- 便于开发的指令
- 虚拟 dom :跨端开发,减少 dom 操作
- 生态系统丰富(路由,仓库,第三方框架)
谈谈你对spa的理解
- 整个项目只有一个页面
- 页面中的内容是动态的,以组件的形式展示,靠路由来映射匹配组件
优点:
- 组件化开发,易于维护
- 页面切换快,体验好
- 前后端分离,提高开发效率
- 减轻服务器压力,提高性能
缺点:
- 初次加载慢
- 不利于SEO(可以使用 SSR)
说说你的 vue 生命周期的理解
vue 组件从创建到销毁的过程,其中官方提供了一系列的钩子函数
左部分是 Vue3,右边是 Vue2
- setup == beforeCreate + created
- onBeforeMount == beforeMount
- onMounted == mounted
- onBeforeUpdate == beforeUpdate
- onUpdated == updated
- onBeforeUnmount == beforeUnmount
- onUnmounted == unmounted
- onActivated == activated
- onDeactivated == deactivated
如果想要了解更多的话,可以看 Vue 的官网:cn.vuejs.org/api/ 响应式api也可以了解一下
说说你对双向绑定的理解
- 是什么: v-model = v-on + v-bind
修改数据,页面同步更新,页面内容修改,数据也会同步更新
- 原理: model view viewModel
- ViewModel: 1. Observer 监听器 2. Compile 解析器
(这个会有点复杂,后面出一篇文章来讲解)
- 双向绑定的原理:
- 单向绑定:变量被处理成响应式的过程中会为变量做依赖收集,当变量的值变更时,触发 setter ,并执行依赖,导致视图更新
- 双向绑定:视图更新用等同于用户触发了 input 函数,修改响应式变量,进而又导致 setter 触发
vue 的组件通信
我这里有一篇文章写的比较详细:juejin.cn/post/748898…
| 通信方式 | 实现形式 | 数据流向 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|---|
| Props 传值 | v-bind + defineProps | 父→子 | 父子数据传递 | 类型安全/单向数据流 | 多层传递繁琐 |
| v-model 双向绑定 | v-model:prop 语法糖 | 父子双向 | 表单组件/双向绑定 | 简化代码/标准语法 | 需严格定义 update 事件 |
| 自定义事件 | defineEmits + v-on | 子→父 | 子组件通知父组件 | 显式数据流 | 需维护事件名 |
| 组件实例暴露 | defineExpose + ref | 父访问子 | 调用子组件方法/状态 | 灵活 | 破坏封装性 |
| Provide/Inject | provide + inject | 祖先→后代 | 跨层级共享 | 避免逐层传递 | 数据流向不透明 |
| 共享状态对象 | 响应式对象模块化 | 任意组件 | 简单兄弟通信 | 实现简单 | 难以维护 |
| Pinia 状态库 | defineStore + useStore | 全局 | 复杂应用状态管理 | 调试工具支持 | 需学习额外 API |
watch 和 computed 的区别
| 特性 | computed | watch |
|---|---|---|
| 设计目的 | 派生新数据(基于其他数据计算得到结果) | 监听数据变化并执行副作用(如异步操作、DOM 操作) |
| 是否有返回值 | ✅ 必须有返回值 | ❌ 无返回值 |
| 缓存机制 | ✅ 依赖不变时直接返回缓存结果 | ❌ 每次数据变化都触发回调 |
| 依赖追踪 | 自动追踪函数内所有响应式依赖 | 需手动指定监听的目标数据 |
| 适用场景 | 模板中简化复杂逻辑、需要缓存结果的计算(如格式化数据、过滤列表) | 异步任务(如接口请求)、监听变化执行操作(如日志记录)、需要旧值和新值对比 |
| 性能优化 | 高效(减少重复计算) | 需谨慎使用(避免高频监听导致性能问题) |
| 是否支持异步 | ❌ 计算函数必须是同步的 | ✅ 可在回调中执行异步操作 |
| 语法(Options API) | 在 computed 选项中定义函数 | 在 watch 选项中定义对象或函数 |
| 初始化是否触发 | ✅ 默认立即计算并缓存结果 | ❌ 默认不触发(需设置 immediate: true) |
v-if 和 v-show 的区别
1. 控制手段: v-if 为 false 时,不加载 dom 树, v-show = false,是用 display=none
2. 编译不同: v-if 控制的组件会触发生命周期(有重新编译和卸载的过程),而 v-show 不会
3. 性能: v-if 有更高的切换开销
v-if 可以和 v-for 一起使用吗
- vue3: 可以,但不推荐,v-if 的优先级比 v-for 高
- vue2 : 不行,v-for 的优先级比 v-if 高
SPA 首屏加载优化
- 首屏加载慢原因
- 单页应用需要把所有的页面代码都执行完毕,首屏才会加载
- 需要加载 js 脚本
- 网络延时
- 优化方法
- 路由懒加载
- SSR 服务端渲染
- 骨架屏
- UI 框架按需加载
为什么 vue 支持双向绑定,但是数据流是单向的
Vue 的单向数据流通过 props 向下传递、事件向上通信 的机制,平衡了灵活性与可控性。尽管提供了 v-model 等便捷语法,底层仍严格遵循单向原则,确保数据变化的可预测性和可维护性。这种设计尤其适合复杂应用的长期迭代。
- 可维护性:组件关系清晰,数据变更路径明确(适合大型项目)。
- 调试友好,来源明确:通过 Vue Devtools 可直接追踪数据变化来源。
- 避免副作用:子组件无法意外污染父组件状态(如直接修改对象属性)。
为什么 data 要是一个函数
- 如果 data 是一个对象,那么当组件被多次复用时,会导致数据共享,会出现数据污染的问题。因为 data 必须是一个函数,返回一个对象,每个组件的实例都有一个自己的对象
说说你对 vue 中的 nextTick 的理解
是什么: vue 官方给我们提供的异步函数,作用是在 dom 更新完成之后执行延迟回调
应用场景: 当我们需要 dom 更新之后的数据
原理: 在拥有 MutationObserver 的环境中,使用 MutationObserver监听,在 dom 更新后触发回调,是微任务在不支持 MutationObserver 的环境中,使用 setTimeOut 来触发回调,是宏任务
vue2 和 vue3 了解吗,有什么区别?
- 静态缓存
-
静态提升(Hoist Static) :将模板中的静态节点(无动态绑定的元素)提升到渲染函数外部,复用同一个虚拟 DOM 节点,减少重渲染开销。
-
示例:
<!-- 模板 --> <div> <h1>Static Title</h1> <!-- 静态节点,会被缓存 --> <p>{{ dynamicText }}</p> </div>
- diff 算法
-
Vue2(Object.defineProperty) :
- 递归遍历对象属性,通过
getter/setter拦截数据变化。 - 缺点:无法检测对象新增/删除属性(需用
Vue.set/Vue.delete),对数组需重写方法(如push)。
- 递归遍历对象属性,通过
-
Vue3(Proxy) :
-
使用
Proxy代理整个对象,直接监听对象/数组的变化。 -
优势:
- 支持动态新增/删除属性。
- 原生支持数组索引修改和
length变化。 - 性能更高,惰性响应(按需触发更新)。
-
- v-if 和 v-for 的优先级
- Vue2:
v-for优先级高于v-if,导致循环所有元素后再条件过滤,性能浪费。 - Vue3:
v-if优先级高于v-for,避免不必要的循环。
- 生命周期
-
Vue2:
beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed。 -
Vue3:
-
移除
beforeCreate和created,用setup替代。 -
其他钩子改名(更语义化):
beforeDestroy→onBeforeUnmountdestroyed→onUnmounted
-
- 组合式 api
-
Vue2(Options API) :逻辑分散在
data、methods、computed等选项中,大型组件难以维护。 -
Vue3(Composition API) :
- 使用
setup函数集中管理逻辑,通过函数组合实现高复用性。
- 使用
- 响应式原理
-
Vue2(Object.defineProperty) :
- 递归遍历对象属性,通过
getter/setter拦截数据变化。 - 缺点:无法检测对象新增/删除属性(需用
Vue.set/Vue.delete),对数组需重写方法(如push)。
- 递归遍历对象属性,通过
-
Vue3(Proxy) :
-
使用
Proxy代理整个对象,直接监听对象/数组的变化。 -
优势:
- 支持动态新增/删除属性。
- 原生支持数组索引修改和
length变化。 - 性能更高,惰性响应(按需触发更新)。
-
- 更好的TS支持
- Vue3 源码用 TS 重写,提供更好的类型推导。
- 性能
- Vue3 打包体积更小(Tree-shaking 优化),运行速度更快。
题外话
欢迎在评论区留下你的最难Vue面试题,互助答疑!