波珠的第一场前端面试,小厂,问的都是基础,但是波珠太菜了,八股背的不够多不够熟 准备不够充分,面得很烂,下面是正文
预览部分:
笔试:toRefs,vue怎么加载更快,keep-alive怎么缓存,$nextTick,ref和reactive区别,深拷贝浅拷贝区别,深拷贝怎么实现
面试:自我介绍,用three.js做数据大屏数据属性是怎么交互的,vue2和vue3生命周期区别,vue3项目一般做什么,开源主要做了啥,对象能用ref吗?怎么实现,vite和webpack区别,职业发展规划
一.toRefs
答案:
.toRefs是 Vue 3 提供的工具方法,用于将响应式对象的每个属性转成独立的 ref,解决 解构后丢失响应式 的问题
简单示例:
import { reactive, toRefs } from 'vue'
const state = reactive({ count: 0, name: '鼠鼠' })
const { count, name } = toRefs(state)
count.value++ // 响应式正常工作
如果直接解构 reactive 对象:
const { count } = state
count++ // 失去响应式
ref → 一个值响应式
reactive → 整个对象响应式
toRef → 单个属性响应式
toRefs → 批量属性响应式
二.vue怎么加载更快
记忆口诀:"三减两压一缓存"
三减:减少首屏体积(路由懒加载、按需引入、CDN)
两压:压缩 JS/CSS + 图片压缩(Gzip/webp)
一缓存:浏览器缓存 + HTTP 缓存
三.keep-alive怎么缓存
答案:
keep-alive通过缓存组件实例 + LRU 策略,在切换组件时复用已渲染的实例,提升性能并保留状态
解释理解:
LRU机制:当缓存数量超出 max,会删除最久未使用的组件实例
| 生命周期 | 普通组件 | keep-alive 组件 |
|---|---|---|
| 挂载 | created → mounted | created → mounted |
| 切换隐藏 | beforeUnmount → unmounted | deactivated(组件被缓存,但未真正卸载) |
| 切换激活 | 重新执行 mounted | activated(组件从缓存中被激活) |
四.$nextTick
答案:
$nextTick用于在 DOM 更新完成后 立即执行回调函数,保证拿到最新的 DOM 状态
解释理解:
- Vue 的 响应式更新是异步批处理 ,当数据变化时,Vue 不会立即更新 DOM,而是开启一个任务队列
- 在当前事件循环结束后,统一执行 DOM 更新,避免频繁操作 DOM 造成性能浪费
- Vue 内部实现
$nextTick使用了 微任务优先、宏任务兜底 的机制,保证了$nextTick回调总是在 DOM 更新后立刻执行,而且内部使用Promise.resolve().then(),执行顺序比普通的setTimeout更快
五.ref和reactive区别
ref 适合处理 基本类型 或单个值,通过 .value 访问。
reactive 适合处理 对象或数组,返回的是一个 Proxy 代理对象,可直接访问属性。
| 特性 | ref | reactive |
|---|---|---|
| 数据类型 | 基本类型、对象都可 | 仅对象、数组、集合类型 |
| 访问方式 | 通过 .value 访问 | 直接访问属性 |
| 底层原理 | 基本类型用 value 包装,内部调用 reactive 处理对象 | 通过 Proxy 代理整个对象 |
| 使用场景 | 单值状态、标志位 | 复杂对象、表单、列表数据 |
六.深拷贝浅拷贝区别,深拷贝怎么实现
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 拷贝层级 | 只拷贝一层 | 递归拷贝所有层级 |
| 引用类型影响 | 修改子对象会互相影响 | 完全独立互不影响 |
| 性能 | 高(不递归,简单) | 低(递归遍历,耗性能) |
浅拷贝的实现:
Object.assign() 或 扩展运算符 {...obj}。
深拷贝的实现:
方法一:JSON.parse(JSON.stringify())
最简单直接,但是会丢失 undefined、Symbol、函数,无法处理循环引用,报错
JSON.stringify() 用于把对象序列化成 JSON 字符串,JSON.parse() 用于将 JSON 字符串反序列化为对象;结合使用时,相当于先把对象“拍扁”,再重建一个新对象,从而实现深拷贝
const obj = { a: 1, b: { c: 2 }, d: undefined, e: () => {} };
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy);
// { a: 1, b: { c: 2 } } // undefined 和函数丢失
方法二:递归拷贝
可处理循环引用,可保留复杂数据类型;实现复杂,要考虑多种复杂对象如Set的情况
方法三:structuredClone()(推荐)
性能好,能拷贝Map、Set等复杂结构,能处理循环引用;兼容性不足(Node 17+,Chrome 98+)
const obj = { a: 1, b: { c: 2 } };
const copy = structuredClone(obj);
copy.b.c = 3;
console.log(obj.b.c); // 2
方法四:第三方库 lodash.cloneDeep()
可靠性高;需要引入第三方库,增加包体积
import cloneDeep from 'lodash/cloneDeep';
const copy = cloneDeep(obj);
七.three.js做数据大屏数据属性是怎么交互的
在 three.js 数据大屏中,通过 数据绑定到三维模型,结合 Raycaster 进行交互检测,并实时更新 position、scale、color 等属性,使用动画库实现平滑过渡,最终形成实时、动态、可交互的三维可视化场景。 同时,利用实例化渲染和分层更新等优化手段,保证大屏性能流畅。
八.vue2和vue3生命周期区别
Vue 3 所有生命周期函数都加 on 前缀,destroy 变 unmount。
| 阶段 | Vue 2 | Vue 3 (组合式 API) |
|---|---|---|
| 创建前 | beforeCreate | 无对应 → 逻辑可放在 setup 顶部 |
| 创建后 | created | 无对应 → 逻辑可放在 setup 顶部 |
| 挂载前 | beforeMount | onBeforeMount |
| 挂载后 | mounted | onMounted |
| 更新前 | beforeUpdate | onBeforeUpdate |
| 更新后 | updated | onUpdated |
| 销毁前 | beforeDestroy | onBeforeUnmount |
| 销毁后 | destroyed | onUnmounted |
| 错误捕获 | errorCaptured | onErrorCaptured |
| 新钩子 | 无 | onRenderTracked / onRenderTriggered |
九.对象能用ref吗?怎么实现
能,ref包裹对象时内部会使用 reactive 处理对象,使其深层属性响应式。
实现方式:
import { ref } from 'vue'
const state = ref({ count: 0 }) // 对象也可以用 ref
state.value.count++ // 修改对象属性需要通过 value
十.vite和webpack区别
| 特性 | Webpack | Vite |
|---|---|---|
| 启动速度 | 启动慢,需要先打包整个项目 | 启动快,按需编译,直接基于 ESM |
| 热更新 (HMR) | 需重新打包依赖链,速度较慢 | 直接替换模块文件,毫秒级更新 |
| 开发原理 | 运行前必须构建一个打包产物 | 浏览器原生支持 ESM,未访问的文件不编译 |
| 生产构建 | 自己实现打包 | 基于 Rollup,优化 Tree-shaking |
| 生态成熟度 | 生态最完善,插件丰富 | 生态逐渐完善,但整体比 Webpack 新 |
| 配置复杂度 | 配置繁琐,学习曲线陡峭 | 配置简单,开箱即用 |
| 适合场景 | 复杂项目、大型企业项目 | 中小型项目、快速原型开发 |
简单记:
Vite 开发快 → 原生 ESM + 按需编译
Webpack 构建强 → 生态成熟 + 插件丰富
开发选 Vite,兼容选 Webpack