TL;DR:Vue3 + OpenLayers 地图白屏且控制台无报错,按「容器尺寸 → 初始化时机 → viewport 数量 → 中心点投影 → 底图 URL」这个顺序查,90% 的案例停在第一步。文末 Demo 可一键切换错误 / 正确两种状态,浏览器直接打开即可复现。
之前给客户做 Vue3 + OpenLayers 的水利一张图,页面切到地图 tab 时整块空白,F12 里干干净净,连瓦片请求都没有。查了快两个小时,最后发现是容器高度为 0 时就把 Map new 出来了。
这种 "无报错白屏" 是 WebGIS 前端最磨人的问题 ------ 报错还能搜,不报错全靠猜。这篇把排查顺序和每个环节的验证方法一次说清,本机 Chrome 实测,2026-10。
先分清:真白屏还是 "假白屏"
白屏分两种,排查路径完全不同:
-
真白屏 :容器里连
.ol-viewport都没有,或者 canvas 尺寸是 0×0------ 初始化时机问题; -
假白屏:viewport 存在,但地图定位到了别处,或瓦片没加载出来 ------ 投影 / 请求问题。
判断方法:F12 里查一下容器内有没有 .ol-viewport。有,就是假白屏,直接跳到第四、五步;没有,从第一步开始。
第一步:容器尺寸,绝大多数的坑都在这
常见三种来源:
-
弹窗 / 抽屉未展开就初始化地图;
-
v-if控制的地图容器还在渲染中; -
容器设了
height: 0(自适应布局没给高度)。
验证只需一行:
javascript
console.log(container.getBoundingClientRect())
// 宽或高为 0,就是它
复现一下错误写法 ------ 容器高度 0 时初始化,页面白屏且控制台无任何报错:
javascript
// 错误:容器尺寸为 0 时初始化
const map = new Map({
target: container, // getBoundingClientRect() 高度为 0
layers: [new TileLayer({ source: new XYZ({ url: gaodeUrl }) })],
view: new View({ center: fromLonLat([113.2644, 23.1291]), zoom: 12 })
})
正确写法是等容器有尺寸再初始化:
javascript
// 正确:先等容器就绪,确认有尺寸再 new Map
await nextTick()
const rect = container.getBoundingClientRect()
if (rect.width === 0 || rect.height === 0) return // 容器不可见,先别初始化
const map = new Map({ target: container, /* ... */ })
第二步:初始化时机,弹窗里最常见的坑
el-dialog 这类弹窗默认懒渲染 + display: none,直接在 onMounted 里 new Map,容器根本还没挂出来。要用弹窗的 opened 回调,或者 nextTick 后检查 offsetParent------display: none 时它是 null:
javascript
if (container.offsetParent === null) {
// 容器处于隐藏状态,地图初始化会白屏,等显示后再做
}
第三步:ol-viewport 重复创建,路由切换的隐性泄漏
KeepAlive 缓存 + 路由复用是重灾区:每次进页面 new 一个 Map,target 相同,OL 会在容器里再插一个 .ol-viewport,旧实例没销毁 ------ 轻则叠影、事件错乱,重则白屏加内存上涨。
排查看数量:
javascript
container.querySelectorAll('.ol-viewport').length // 应为 1,大于 1 就是重复创建
修复是卸载时销毁实例:
javascript
onBeforeUnmount(() => {
map?.setTarget(undefined) // 从容器上摘除,再置空引用
map = null
})
中心点投影:白屏也可能是 "定位到海里"
View 的 center 默认是 Web 墨卡托(EPSG:3857)。直接塞经纬度(EPSG:4326),地图会定位到 (113, 23) 对应的墨卡托位置 ------ 那在赤道附近的海域,页面同样是一片空白,看起来就是白屏:
javascript
import { fromLonLat } from 'ol/proj'
// 正确:经纬度必须转投影
view: new View({ center: fromLonLat([113.2644, 23.1291]), zoom: 12 })
底图 URL 不对,请求 404 也会白屏
高德源在 OpenLayers 里必须写数字占位符 {1-4}。写成 Leaflet 的 {s},瓦片请求会打到字面量域名上,全部 404,底图空白:
javascript
// OpenLayers 的 XYZ 源不认 {s},必须写 {1-4}
const gaodeUrl =
'https://webrd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
// Leaflet 才用 {s}:https://webrd0{s}.is.autonavi.com/...
按上面顺序修完,地图正常渲染: 
⚠️ 三个容易被忽略的点
-
排查 "无报错白屏" 先看 Network 面板:一片空白(无瓦片请求)→ 初始化 / 投影问题;有请求但 404/403 → 底图 URL 或 key 问题;
-
display: none的容器getBoundingClientRect返回 0,但元素其实 "存在"------ 别只看存在性,要看尺寸; -
地图组件卸载不销毁,路由来回切几次后不只白屏,还会把内存吃上去,最后变成 "用着用着就卡"。
一句话口诀:先查尺寸再查时机,viewport 只留一个,经纬度记得转投影。
小结
| 排查项 | 验证方法 | 常见来源 |
|---|---|---|
| 容器尺寸 | getBoundingClientRect() 宽高 |
弹窗未展开 /height:0 |
| 初始化时机 | offsetParent === null |
el-dialog 懒渲染 |
| viewport 数量 | querySelectorAll('.ol-viewport').length |
路由复用未销毁 |
| 中心点投影 | 是否用了 fromLonLat |
直接塞经纬度 |
| 底图 URL | Network 面板瓦片状态 | {s} vs {1-4} |
排查顺序也有例外 ------ 如果页面之前能正常显示、某次改动后才白,优先看改动点(比如加了 KeepAlive、换了容器结构)。上面的顺序是给 "一上来就白" 的情况用的。
📦 Demo 见 gitee.com/shijiansuip...(浏览器直接打开即可复现,页面内可一键切换错误 / 正确两种状态)。
标签:vue3、webgis、openlayers