1.前端性能优化?
整体分为四大方向:网络加载优化、渲染优化、代码与工程化优化、运行时体验优化
一、网络层面优化(首屏核心)
1. 资源体积减小
2.图片优化
3. 缓存策略(减少重复请求)
4. 请求优化
二、浏览器渲染层面优化
1. 减少重排 (Reflow)、重绘 (Repaint)
- 重排:元素几何尺寸、位置变化(开销大)
- 重绘:颜色、背景变化,布局不变
优化手段:
2. DOM 操作优化
- 减少频繁操作真实 DOM,利用虚拟 DOM;
- 大数据列表使用虚拟滚动,只渲染可视区域 DOM;
- 及时移除无用 DOM 事件、定时器,防止内存泄漏。
三、Vue/React 框架专项优化
- v-for 添加唯一 key,不要和 v-if 写同一标签;
- 大数据静态列表使用 Object.freeze 取消响应式;
- 合理区分 v-if / v-show;
- computed 缓存计算结果,代替模板复杂表达式;
- keep-alive 缓存页面组件,避免重复渲染;
- 合理使用 shallowRef/shallowReactive 浅层响应式,减少递归劫持;
- Vue3 利用编译优化:静态提升、PatchFlags。
四、工程化 & 部署优化
- 生产环境关闭 source-map;
- externals CDN 引入大型依赖(vue、echarts 等),不打入 bundle;
- 拆分 chunk,分包策略,避免单个 js 体积过大;
- 服务端优化:Nginx 配置、history 模式重定向。
五、用户体验优化(感知性能)
六、精简版
- 网络优化:资源压缩、分包懒加载、Gzip、CDN、图片优化、浏览器缓存;
- 渲染优化:减少重排重绘,动画使用 transform,批量操作 DOM;大数据列表虚拟滚动;
- 框架层面:合理使用响应式 API、computed 缓存、keep-alive、规范 v-for/v-if;
- 工程化与体验:Tree-Shaking、externals、关闭 sourceMap;骨架屏提升感知体验;极端场景采用 SSR / 预渲染。
2.如何解决大量数据的渲染?
方案 1:分页加载(最常用,业务首选)
不和前端承担海量 DOM 渲染压力,后端分页,每次只请求一页数据(20/50 条)。
适用:后台管理表格、普通列表。
方案 2:虚拟列表(虚拟滚动 Virtual List,高频面试重点)
只渲染可视区域内的 DOM,不在视口的数据不生成真实 DOM。 通过滚动高度计算,利用占位元素撑起滚动条,滚动时动态替换可视区域数据。
Vue 常用库
- vue2:vue-virtual-scroller
- vue3:vue-virtual-scroller、vueuse/useVirtualList
简易核心思路(手写原理面试可能问)
方案 3:时间分片(requestIdleCallback /setTimeout 分片渲染)
不一次性循环渲染全部数据,把数据切分成小块,利用浏览器空闲时间分批插入 DOM,避免长任务阻塞主线程造成页面卡死。
缺点:依旧会渲染全部 DOM,只是不会瞬间卡死,数据极大时内存依然持续上涨。 适用:几百条中等数据,上万条不推荐。
// 伪代码
let allList = 一万条数据
let page = 0
const size = 30
function render() {
const fragment = document.createDocumentFragment()
const slice = allList.slice(page*size, (page+1)*size)
// 渲染slice
page++
if(page*size < allList.length){
requestIdleCallback(render)
}
}
render()
方案 4:取消不必要的响应式优化
数据是纯展示、无需修改
const list = Object.freeze(后端返回数组)
Object.freeze 让 Vue 不再递归进行响应式劫持,节省初始化耗时。
方案 5:后端优化
大量数据直接渲染会创建过多 DOM 阻塞主线程,造成页面卡顿。 优先方案: ① 和后端约定分页加载或无限滚动,减少单次数据量; ② 不能分页时使用虚拟列表(虚拟滚动),仅渲染可视区域 DOM,性能最优; ③ 少量大数据采用时间分片分批渲染,避免一次性渲染阻塞页面; ④ 纯展示数据使用 Object.freeze 关闭响应式,减少响应式开销。
3.跨浏览器兼容问题
一、什么是跨浏览器兼容
不同浏览器(Chrome、Firefox、Edge、Safari,老旧浏览器 IE11)内核不同、标准实现有差异,导致页面样式错乱、JS 报错、功能失效,需要做兼容处理。
浏览器内核
- Chrome/Edge:Blink
- Firefox:Gecko
- Safari:WebKit
- IE:Trident
二、CSS 层面常见兼容与解决方案
1. 私有前缀
部分 CSS 新属性需要浏览器厂商前缀 -webkit-(webkit 内核)、-moz-(firefox)、-ms-(IE)
/* 原生 */
transform: translate(0);
/* 兼容写法 */
-webkit-transform: translate(0);
transform: translate(0);
工程化方案:使用 autoprefixer + postcss,自动添加前缀,不用手动写。
2. 经典样式差异
IE 怪异模式下 box-sizing: border-box 行为差异;统一设置:
*{box-sizing: border-box; margin:0; padding:0;}
-
默认样式不同 各浏览器标签自带 margin/padding、字体不一样。 解决:Normalize.css(保留有用默认样式) / Reset.css(全部清零)
-
Flex 在老旧 Safari 存在布局 bug,部分属性需要 – webkit 前缀
-
IE 不支持部分新 CSS:flex-gap、clip-path、css 变量var()
三、JS 层面兼容问题
1. API 兼容性
- IE11 不支持 ES6+:let/const、箭头函数、Promise、Array.prototype.includes、forEach
- 部分浏览器方法名称不一致:
- 事件监听:标准 addEventListener;IE 旧版 attachEvent
- 获取滚动条:scrollTop,标准与 IE 取值存在差异
- ajax:IE 早期 ActiveXObject,标准 XMLHttpRequest
2. 解决手段
3. 事件兼容(面试手写常考)
// 绑定事件
function on(el, type, handler) {
if(el.addEventListener){
el.addEventListener(type, handler)
}else{
el.attachEvent('on'+type, handler) // IE低版本
}
}
