Skip to content

第 13 章 性能与最佳实践 ​

地图应用的性能坑往往在使用量上来后才暴露。本章把前文散落的性能要点收敛成一份 可操作的清单,帮你在「功能」与「流畅」之间拿稳平衡。

13.1 三种渲染方式的取舍 ​

方式渲染机制适用规模交互粒度
MapMarker(DOM)真实 DOM 节点数百每点独立、富样式
MapGeoJSON 点图层WebGL数千~数万统一样式、批量
MapClusterLayerWebGL + 聚合数千~数十万聚合/单点

经验法则:点数过千,优先 MapClusterLayer 或 MapGeoJSON 点图层;只有需要 「每个标记都是独特 DOM 组件」时才用 MapMarker。

13.2 受控模式的代价 ​

受控模式(viewport + onViewportChange)会在每一次平移、缩放、旋转时触发 回调,频繁 onViewportChange 可能带来重渲染压力。建议:

  • 仅在确实需要「地图状态」与「应用状态」同步时启用;
  • 若只想「监听」变化,单独用 onViewportChange 而不传 viewport,地图仍是非 受控的,回调不会驱动重渲染;
  • 对高频回调做节流(throttle),或只记录最终值。

13.3 事件监听必须清理 ​

自定义 map.on() 监听要在组件卸载时 map.off()(见第 11 章)。未清理的 监听会随组件反复挂载而累积,导致内存泄漏与诡异行为。

13.4 图层增删先判定 ​

直接用 map 增删图层时,先 getSource / getLayer 判断存在性再添加,避免 重复添加报错;卸载时移除自己创建的图层与 source。mapcn 的内置图层(Route/Arc/ GeoJSON/Cluster)已自动管理生命周期,无需你清理。

13.5 大数据量的取数策略 ​

  • 静态大数据:优先用 URL 让组件 fetch,或内联一次性数据,避免每次渲染重建 大型对象;
  • 动态数据:用 useMemo 缓存 GeoJSON 结构,仅在数据真正变化时更新,减少 fetch 调用;
  • 表达式优于循环:用 MapLibre 表达式(如 interpolate / match)按字段着色, 而不是为每个要素单独建图层。

13.6 容器与尺寸 ​

  • 地图容器必须有确定高度,否则塌陷为 0;
  • 频繁改变容器尺寸时,MapLibre 会自动重排,但应避免在动画帧里反复改尺寸;
  • 移动端注意 100vh 在地址栏收起时的抖动,必要时用 100dvh 或固定高度。

13.7 可访问性与降级 ​

  • 给交互控件加 aria-label(mapcn 已为内置按钮加好);
  • 地图本身对屏幕阅读器不友好,关键数据应同时在列表/表格中以文本形式提供;
  • 地理定位等依赖用户授权的能力,要在被拒绝时优雅降级(见第 4 章 showLocate)。

13.8 一份检查清单 ​

上线前对照:

  • [ ] 点数规模是否选对了渲染方式?
  • [ ] 受控模式是否必要?回调是否节流?
  • [ ] 所有 map.on() 都有对应 map.off()?
  • [ ] 自定义图层是否在卸载时移除?
  • [ ] 大数据是否用 useMemo / URL / 表达式优化?
  • [ ] 容器高度是否确定、移动端是否稳定?

本章小结 ​

  • 渲染方式按规模取舍:数百用 DOM 标记,数千以上用图层/聚合;
  • 受控模式按需启用,监听变化可用单向 onViewportChange;
  • 事件监听与自定义图层务必清理;
  • 用 useMemo、URL 取数、表达式着色优化大数据;
  • 容器高度确定、关键数据文本化,是可访问与稳定的底线。

下一章,我们用一个完整案例把所学串起来。

基于 mapcn 官方文档整理 · AI 辅助编撰