前端业务痛点拆解:大文件上传、接口并发… 这些场景该这么破?
1. ECharts 地图上万级 Icon 展示与瓦片化优化
直接渲染万级 Icon 会导致:
- 性能瓶颈:大量 DOM 节点或 Canvas 元素渲染阻塞主线程,引发卡顿
- 视觉混乱:密集 Icon 重叠,信息可读性差
如果有一万个icon需要在echarts地图上展示,可以考虑采用热力图或者聚合图等方式进行展示。这样可以避免大量的marker对页面性能造成影响。同时,如果地图数据过大,可以考虑使用瓦片化技术来进行优化。 瓦片化是一种将地图数据分成小块,以瓦片形式进行加载的技术。通过瓦片化,可以将地图数据分割成多个小块,每个小块都是一个完整的图块,独立进行加载和展示,从而提高页面的性能和响应速度。
解决可以从以下几个方法入手:
1. 分层聚合渲染(推荐)
-
原理:根据地图缩放层级动态聚合 Icon,层级较低时显示聚合点(如 “100+”),层级足够高时展示具体 Icon
-
实现步骤:
// ECharts 地图分层配置示例 option = { series: [{ type: 'map', map: 'china', zoom: 5, // 初始缩放层级 label: { show: false }, roam: true, // 开启缩放交互 data: generateMassData(10000), // 生成模拟数据(包含经纬度、数值) // 自定义聚合规则(根据缩放层级切换渲染策略) emphasis: { label: { show: true } }, itemStyle: { normal: { areaColor: '#fff', borderColor: '#111' } }, // 关键:使用自定义渲染器处理海量数据 progressive: 400, // 渐进式渲染,每次处理 400 个数据点 progressiveThreshold: 3000 // 当数据量超过 3000 时启用渐进式渲染 }] }; // 聚合函数:根据当前缩放层级分组 function aggregateData(data, zoom) { if (zoom < 6) return [{ name: '全国', value: data.length }]; // 层级低时显示总数 if (zoom < 8) return data.groupBy('province'); // 层级中等时按省份聚合 return data; // 层级高时显示全部 }
2. 瓦片化(Tile-Based)方案
-
核心思想:将地图划分为固定大小的瓦片(如 256x256 像素),每个瓦片独立加载和渲染
-
技术实现: 使用
Canvas或WebGL渲染瓦片,通过视口滚动加载当前可见区域的瓦片 -
优势:1. 按需加载,减少内存占用 2. 支持离线缓存,提升二次访问速度
-
适用场景: 超大规模地图(如全球数据)、需要频繁缩放的场景
3. 替代方案:热力图 / 密度图
// 热力图配置示例
option = {
series: [{
type: 'heatmap',
coordinateSystem: 'geo',
data: data.map(item => [item.lng, item.lat, item.value]),
pointSize: 8, // 热点半径
blurSize: 15, // 高斯模糊范围
emphasis: { itemStyle: { opacity: 0.8 } }
}]
};
2. 1000w 行表格如何渲染?
直接渲染千万行数据会导致:
- 内存爆炸:DOM 节点数量突破浏览器极限
- 交互卡顿:滚动、筛选等操作触发重排 / 重绘耗时严重
eg:维格表、飞书表格、钉钉表格、在线表格等追求大数据量
可以从以下几个方面考虑:
1. dom
2. 虚拟表格
3. canvas table
4.可视区绘制算法优化
5.canvas 结合 Webassembly 技术实现 (Skia + Webassembly)
3. js 超过 Number 最大值的数怎么处理?
- 使用 bigint 来处理大数据
// 基本用法
const bigNumber = 123456789012345678901234567890n; // 末尾加 `n` 标识 BigInt
const result = bigNumber + 987654321098765432109876543210n; // 直接运算
// 注意事项:
// - 不能与普通 Number 混合运算
// - 无浮点型,需手动处理小数位(如以分为单位存储整数)
- Decimal.js 库来处理
// 金融场景:精确计算金额
import Decimal from 'decimal.js';
const price = new Decimal('199.99');
const quantity = new Decimal('10');
const total = price.mul(quantity).toFixed(2); // 1999.90(避免浮点精度问题)
- 使用 big.js 库 格式化成用户好读的格式
// 科学计算:处理超大指数
import Big from 'big.js';
const avogadro = new Big('6.02214076e23');
const result = avogadro.times('1e20').toString(); // 6.02214076e43
4. 如何解决页面请求接口大规模并发问题?
处理:滑动窗口,算法,专门来控制流量
背景:数据采集平台,低代码编辑平台,有序相对稳定发送到后端
方案:
- 请求队列: queue.push() queue.shift() 进行封装
- 防抖/节流:
防抖—确保在指定时间内函数只执行一次,常用语输入框搜索建议
节流—确保在指定时间间隔内函数执行一次,常用语窗口的 resize,scroll 事件。
【简单描述:在不调用库的情况下,如何实现,如何封装】
- 分页加载
落地及反思:
- 大数据量请求场景下,我们选用了请求队列,我主导封装了请求队列
- 防抖截流,用户交互层民商解决减少请求的处理
- 分页/滚动加载,可视区绘制
5. 请说说大文件上传?
背景:eg Ai 产品方面,设计到用户自定义模型(1G 以上)
存在问题:
- 网络断开之后,之前传的没了
- 传着传着 网络波动了,结果啥都没了
- 关机了,想接着传,做不到
专业术语:
- 断点续传
- 断开重连重传
- 切片上传
方案:
-前端切片 chunk 1024M(1048576K),500K, const size = 1048576/500
-将切片传递给后端,切的片要取名:hash,index
-后端组合切片
前端切片主进程做卡顿, web-worker 多线程切片,处理完后交给主线程发送。切完后,将 blob 存储到 IndexedDB,下次用户进来之后,嗅探一下是否存在未完成上传的切片,有就尝试继续上传。引入 websocket 实时通知,和请求序列的控制 wss。
实现:
6. 前端怎么实现页面截图?
背景:
飞书文档,内容在列表页想要查看【此处参考问卷调查的查看】
内容导出为 png
设计类软件,出图
以内容导出为 png 为例:eg 导出医疗单子/文档导出 png
截图方案:
-canvas
-puppeteer(无头 headless 浏览器),无头表格,无头,UI
-html2canvas(canvas)可以降低截图实现的成本
上传 CDN 确保访问 URL 也能获取截图
落地:
考虑三个场景页面截图,全页面截图/局部截图/特定区域截图
-截图工具的时候要考虑通用性,selectereg:body,hedaer 等,通过 dom 选择器去考虑截图范围
-设计具体协议
-函数式/组件式去实现
-隐藏 canvas
7. H5 移动端适配问题如何解决?
背景:项目想支持 PC,移动端
方案:
-根据端来开发不同页面(成本最高)
-根据不同端加载不同的 CSS 样式(可取)
-根据响应式,运行不同的样式规则(常用)
-style 预处理器
需考虑的问题:
### 设置视窗,通过元信息配置 meta
‹meta name="viewport" content="width=device-width, initial-scale=1.0">
###掌握媒体查询
body {
font-size: 16px;
}
/* 在某一些设备尺寸下,size 按需更改*/
/* 当我的尺寸 大于 xxx 小于 xxx 的时候,需要什么样式?*/
@media (min-width: 780px) and (max-width: 1024px) {
body {
font-size: 18px;
}
}