面经-前端
三剑客
div 上下居中对齐的方式
常用 Flexbox 布局
1 | .parent { |
深拷贝与浅拷贝
| 浅拷贝 | 深拷贝 | |
|---|---|---|
| 定义 | 在栈内存中重新开辟一块内存空间,并将拷贝对象储存在栈内存中的数据存放到其中。 | 会另外创造一个一模一样的对象 |
| 优缺点 | 浅拷贝只复制了引用,所以修改新对象会影响到原对象 | 修改新对象不会影响到原对象 |
| 实现方法 | 使用赋值运算符(=)或者Object.assign()函数进行拷贝 | 递归拷贝JSON.parse(JSON.stringify(obj)) 或者…扩展运算符 |
1 | // 浅拷贝 |
cookie、sessionStorage、localStorage 的区别
cookie 是一种在客户端存储少量数据并在每个请求中发送给服务器的机制,而 session 则是在服务器端存储用户状态信息,并通过在客户端和服务器之间传递 Session ID 来保持会话状态。它们的区别在于存储的有效期和作用域的不同。为了解决 HTTP 无状态的问题,通常使用 Cookie 和 Session 等机制来在客户端和服务器之间保持状态。
| 特性 | Cookie | localStorage | sessionStorage |
|---|---|---|---|
| 生命周期 | 默认会话级(关闭浏览器即失效) 可手动设置 Expires 或 Max-Age 延长 |
永久 除非用户手动清除或通过代码删除 | 会话级 仅当前标签页有效,关闭标签页即清除 |
| 存储大小 | 约 4KB | 5-10MB(不同浏览器略有差异) | 约 5MB(不同浏览器略有差异) |
| 作用域(同源策略) | 域名 + 路径(可设Path) 同源且同路径才能共享 |
域名 + 协议 + 端口 同源下所有标签页/窗口共享 | 域名 + 协议 + 端口 仅限同一标签页的同一源 |
| 与服务端交互 | 自动携带(每次HTTP请求都会发送,影响性能) | 不自动发送(纯前端存储) | 不自动发送(纯前端存储) |
作用域的详细解释
- Cookie 的作用域最窄:默认只对当前路径(
/)及其子路径有效,但可以通过Path和Domain参数扩大范围。 - localStorage 的作用域是“同源窗口共用”:打开同一个网站的多个标签页,它们共享同一个
localStorage数据(监听storage事件可实现跨标签页通信)。 - sessionStorage 的作用域是“独立标签页”:即使用户在同一网站通过“新标签页打开链接”,新标签页也会拥有独立的
sessionStorage,与原来的互不影响。
link 和 a 标签的区别
<a>
用户 → 点击 → 跳转
<link>
浏览器 → 发现资源 → 加载/关联
<a> |
<link> |
|
|---|---|---|
| 主要用途 | 页面导航 | 引入/声明外部资源 |
| 用户是否点击 | ✅ 通常点击 | ❌ 不用于点击 |
| 核心属性 | href |
rel + href |
| 是否显示文字 | ✅ | ❌ |
| 示例 | <a href="https://www.baidu.com">百度</a> |
<link rel="stylesheet" href="style.css"> |
注意:这里的rel名称是固定的,常用的有如下:
| rel 值 | 用途 |
|---|---|
icon |
网站标签页图标(favicon) |
stylesheet |
引入 CSS 样式表 |
Vue 中的跨域问题
vue3 在 vite.config.js 中配置
1 | export default defineConfig({ |
浏览器的同源策略会阻止前端(
localhost:92)直接请求后端(localhost:8092),产生跨域。Vite 开发服务器提供了 代理(proxy) 功能,让前端请求先发到 Vite 自身,再由 Vite 转发给后端,从而绕过浏览器的跨域限制。
流程
- 前端请求
http://localhost:92/api/xxx - Vite 开发服务器拦截该请求
- 转发到
http://localhost:8092/api/xxx(服务器之间不存在跨域) - 将后端响应返回给前端
/api/paper单独配置了rewrite去掉/api前缀,说明 paper 模块的后端接口路径不带/api前缀。
如何优化网站性能
- 许多的小图片整合到一张大图片中(精灵图)减少网页的http请求,提升网页加载速度。
- 利用浏览器缓存。
- 图片lazyload 懒加载 提高用户体验。
浏览器缓存参考 面经-计算机网络 中的强缓存和协商缓存
JS 中操作数组的方法
| 顺序 | 方法名 | 功能 | 返回值 | 是否改变原数组 | 版本 |
|---|---|---|---|---|---|
| 1 | push() | (在结尾)向数组添加一或多个元素 | 返回新数组长度 | Y | ES5- |
| 2 | unshift() | (在开头)向数组添加一或多个元素 | 返回新数组长度 | Y | ES5- |
| 3 | pop() | 删除数组的最后一位 | 返回被删除的数据 | Y | ES5- |
| 4 | shift() | 移除数组的第一项 | 返回被删除的数据 | Y | ES5- |
| 5 | reverse() | 反转数组中的元素 | 返回反转后数组 | Y | ES5- |
| 6 | sort() | 以字母顺序(字符串Unicode码点)对数组进行排序 | 返回新数组 | Y | ES5- |
| 7 | splice() | 在指定位置删除指定个数元素,再增加任意个数元素(实现数组任意位置的增删改) | 返回删除的数据所组成的数组 | Y | ES5- |
| 8 | concat() | 通过合并(连接)现有数组来创建一个新数组 | 返回合并之后的数组 | N | ES5- |
| 9 | join() | 用特定的字符,将数组拼接形成字符串(默认”,”) | 返回拼接后的新数组 | N | ES5- |
| 10 | slice() | 截切指定位置的数组 | 被截切的元素形成的新的数组 | N | ES5- |
| 11 | toString() | 将数组转换为字符串 | 新数组 | N | ES5- |
| 12 | valueOf() | 查询数组原始值 | 数组的原始值 | N | ES5- |
| 13 | indexOf() | 查询某个元素在数组中第一次出现的位置 | 存在该元素,返回下标,不存在返回 -1 | N | ES5- |
| 14 | lastIndexOf() | 反向查询数组某个元素在数组中第一次出现的位置 | 存在该元素,返回下标,不存在返回 -1 | N | ES5- |
| 15 | forEach() | (迭代)遍历数组,每次循环中执行传入的回调函数 | 无/(undefined) | N | ES5- |
| 16 | map() | (迭代)遍历数组,每次循环时执行传入的回调函数,根据回调函数的返回值,生成一个新的数组 | 有/自定义 | N | ES5- |
| 17 | filter() | (迭代)遍历数组,每次循环时执行传入的回调函数,回调函数返回一个条件,把满足条件的元素筛选出来放到新数组中 | 满足条件的元素组成的新数组 | N | ES5- |
| 18 | every() | (迭代)判断数组中所有的元素是否满足某个条件 | 全都满足返回true 只要有一个不满足返回false | N | ES5- |
| 19 | some() | (迭代)判断数组中是否存在,满足某个条件的元素 | 只要有一个元素满足条件就返回true,都不满足返回false | N | ES5- |
| 20 | reduce() | (归并)遍历数组,每次循环时执行传入的回调函数,回调函数会返回一个值,将该值作为初始值prev,传入到下一次函数中 | 最终操作的结果 | N | ES5- |
| 21 | reduceRight() | (归并)用法同reduce,只不过是从右向左 | 同reduce | N | ES5- |
| 22 | includes() | 判断一个数组是否包含一个指定的值 | 是返回 true,否则 false | N | ES6 |
| 23 | Array.from() | 接收伪数组,返回对应的真数组 | 对应的真数组 | N |
VUE
对于MVVM的理解?
MVVM 是 Model-View-ViewModel 的缩写,MVVM 的设计原理是基于 MVC 的;它主要的优势在于 View 和 Model 之间是双向数据传递的,视图改变数据就可以改变,数据改变了视图也跟着改变。
| 对比项 | MVC | MVVM |
|---|---|---|
| 通信方向 | 用户操作 → Controller → Model → View(单向为主) | View ↔ ViewModel ↔ Model(双向自动同步) |
| Controller/ViewModel职责 | Controller手动控制数据流向和视图更新。 | ViewModel通过数据绑定自动同步,无需手动操作。 |
| 代码耦合度 | View和Model之间可能直接关联,耦合较高。 | View和Model完全隔离,只通过ViewModel通信,耦合度低。 |
| 适用场景 | 后端开发、小型前端项目。 | 复杂的前端单页应用(SPA),如Vue、React(类MVVM)、Angular。 |
Vue2/3的生命周期
Vue 的生命周期是指一个 Vue 实例从创建、挂载、更新到销毁的完整过程。在这个过程中,Vue 提供了一系列的生命周期钩子函数,让开发者可以在特定的阶段执行自己的逻辑。
Vue 2 的生命周期(共 8 个阶段,11 个钩子)
| 阶段 | 钩子函数 | 触发时机 | 能否操作DOM | 适用场景 |
|---|---|---|---|---|
| 创建阶段 | beforeCreate |
实例初始化后,数据观测和事件配置之前 | ❌ 否 | 很少使用,可用于插件初始化 |
created |
实例创建完成,数据观测、计算属性、方法已配置,但尚未挂载 | ❌ 否 | 最常用:发起 Ajax 请求、初始化数据 | |
| 挂载阶段 | beforeMount |
模板编译完成,即将挂载到DOM之前 | ❌ 否 | 很少使用 |
mounted |
实例已挂载到DOM,el 被新生成的 vm.$el 替换 |
✅ 是 | 操作 DOM、使用第三方库(如 ECharts)初始化图表 | |
| 更新阶段 | beforeUpdate |
数据变化后,虚拟DOM重新渲染和打补丁之前 | ❌ 否 | 在更新前访问现有 DOM 状态,如获取滚动位置 |
updated |
虚拟DOM重新渲染并完成DOM更新后 | ✅ 是 | 执行依赖于 DOM 的操作,但注意避免在此修改数据(死循环) | |
| 销毁阶段 | beforeDestroy |
实例销毁之前(this 仍可访问) |
✅ 是 | 清除定时器、取消订阅、解绑事件监听 |
destroyed |
实例销毁完成后,所有指令解绑,事件监听移除 | ✅ 是 | 收尾清理工作 |
此外,Vue 2 还提供了 3 个特殊场景的钩子:
| 钩子函数 | 触发时机 |
|---|---|
activated |
被 keep-alive 缓存的组件激活时触发 |
deactivated |
被 keep-alive 缓存的组件停用时触发 |
errorCaptured |
当捕获到来自子孙组件的错误时触发 |
Vue 3 的生命周期
Vue 3 保留了 Vue 2 的核心生命周期,但在命名和用法上做了调整:
| Vue 2 钩子 | Vue 3 钩子(Options API) | 变化说明 |
|---|---|---|
beforeCreate |
beforeCreate |
名称不变 |
created |
created |
名称不变 |
beforeMount |
beforeMount |
名称不变 |
mounted |
mounted |
名称不变 |
beforeUpdate |
beforeUpdate |
名称不变 |
updated |
updated |
名称不变 |
beforeDestroy |
beforeUnmount |
⚠️ 重命名,语义更准确 |
destroyed |
unmounted |
⚠️ 重命名,语义更准确 |
activated |
activated |
配合 <KeepAlive> 使用 |
deactivated |
deactivated |
配合 <KeepAlive> 使用 |
errorCaptured |
errorCaptured |
名称不变 |
注:
beforeCreate和created在 Vue 3 中仍然保留,但官方更推荐使用setup()替代。
Vue组件间的参数传递 和父子组件方法调用
Vue的路由实现:hash模式 和 history模式区别,上线有什么区别。
在 Vue Router 中,hash 模式和 history 模式是两种前端路由实现方式,它们的核心区别在于如何管理 URL 以及如何与服务器交互。
| 对比维度 | Hash 模式(默认模式) | History 模式 |
|---|---|---|
| URL 格式 | 带有 # 符号,如 /#/about |
无 #,如 /about |
| 浏览器支持 | 兼容所有现代浏览器(包括 IE) | 需要支持 HTML5 History API(IE10+) |
| 服务器配置 | 无需特殊配置,所有请求都返回 index.html |
需要服务器配置,所有路由路径都要指向 index.html |
Vue路由的钩子函数 (路由守卫)
Vue-router的跳转原理:
vuex是什么?怎么使用?哪种功能场景使用它?
对keep-alive 的了解?
vue深度监听(watch)
vue 怎么缓存 keep-alive
缓存了 突然需要发送请求换数据怎么办
vue原理
v-if和v-for哪个优先级更高? 如果两个同时出现,应该怎么优化得到更好的性能?
你知道vue中的key 和工作原理么?说说你对它的理解
你怎么理解vue中的 diff 算法?
vue3.0 生命周期
vue2 与vue3 的区别
vue和react的区别 (三个角度分析)
