You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mapbox + Vue.js 报错:Style is not done loading 求解决方案

解决Vue.js中Mapbox添加GeoJSON图层时的"Style is not done loading"错误

你遇到的偶发Uncaught (in promise) Error: Style is not done loading问题,核心是当前代码没有可靠地等待Mapbox样式完全加载完成就执行了添加图层的逻辑。你用的mapLoaded变量判断和固定3秒延时都不是靠谱的方式——网络快慢、地图资源加载速度都会影响样式加载的实际时间,延时太短会出错,太长又浪费性能。

修复方案:用Promise封装地图样式加载逻辑

我们可以把地图初始化和样式加载的过程封装成Promise,确保后续的图层添加操作一定在样式加载完成后执行,完全去掉不可靠的延时和变量判断。

修改后的完整组件代码:

export default {
  data() {
    return {
      mapBox: null, // 把地图实例存在组件内部,避免全局污染
      mapBoxBounds: null
    }
  },
  mounted() {
    // 先初始化地图,等待样式加载完成后再执行showParcel
    this.loadMap([this.subjectProperty.longitude, this.subjectProperty.latitude])
      .then(() => {
        this.showParcel();
      })
      .catch(err => {
        console.error('地图初始化失败:', err);
      });
  },
  methods: {
    // 让loadMap返回一个Promise,当style.load触发时resolve
    loadMap(center) {
      return new Promise((resolve, reject) => {
        this.mapBox = new mapboxgl.Map({
          container: 'map',
          zoom: 12,
          pitch: 45,
          center: center,
          style: 'mapbox://styles/mapbox/streets-v10'
        });

        // 监听样式加载完成事件,触发时resolve
        this.mapBox.on('style.load', () => {
          resolve();
        });

        // 可选:监听地图加载失败的情况,避免Promise一直pending
        this.mapBox.on('error', (err) => {
          reject(err);
        });
      });
    },
    showParcel() {
      this.mapBoxBounds = new mapboxgl.LngLatBounds();
      this.parcel.geo_json['geometry']['coordinates'][0].forEach((coord) => {
        this.mapBoxBounds.extend(coord);
      });
      MapBoxObject.addGeoJsonParcels(this.parcel.geo_json);
      MapBoxObject.fitBounds();
    }
  }
}

关键修改点说明:

  • 封装Promise可靠等待样式加载:loadMap方法返回Promise,只有当style.load事件触发时才会resolve,确保后续的showParcel在样式完全就绪后执行,彻底解决偶发错误。
  • 避免全局变量污染:把mapBox实例存在组件的data里,而不是用全局变量,避免多个组件或实例冲突。
  • 移除不可靠的setTimeout和mapLoaded判断:不再依赖固定延时或变量,完全基于Mapbox的原生事件来控制执行顺序。
  • 增加错误捕获:监听error事件并reject Promise,方便排查地图初始化失败的情况。

额外注意事项

如果你的this.parcel.geo_json也是异步获取的(比如从API请求),那还要确保这个数据加载完成后再调用showParcel。可以在mounted里先等待数据请求完成,再初始化地图:

async mounted() {
  // 先等待parcel数据加载完成
  await this.fetchParcelData();
  // 再初始化地图并添加图层
  await this.loadMap([this.subjectProperty.longitude, this.subjectProperty.latitude]);
  this.showParcel();
}

这样就能彻底保证执行顺序:数据就绪 → 地图样式加载完成 → 添加GeoJSON图层,再也不会出现样式未加载完成的错误了。

内容的提问来源于stack exchange,提问作者AKN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:45:51