Mapbox GL的load事件本地正常,部署到Vercel报this.map.on不是函数错误
问题原因分析
- 核心报错
TypeError: this.map.on is not a function的根源是生产环境执行时序和本地开发不一致:本地dev环境热加载的执行时序更宽松,子组件mounted触发时父组件传入的Mapbox实例已经完成初始化,但Vercel部署的生产包执行时序更严格,子组件mounted触发时this.map还只是未完成初始化的空对象,没有挂载对应的Mapbox实例方法。 - 图层可见性未生效是因为你的逻辑绑定了两次
map.load事件:如果Mapbox实例初始化完成后load事件已经触发过,后续绑定的load事件回调不会再执行,两个图层都会沿用默认的可见配置,就会出现同时显示的问题。 - 附加的
manifest.js 404报错和Mapbox逻辑无关,是Nuxt的PWA/manifest配置错误导致。
修复方案
1. 改造子组件的执行逻辑,保证Map实例就绪后再操作
新增前置校验,同时避免重复绑定load事件:
export default { props: { map: { type: Object, required: true } }, data: () => ({ layerIds: ['Zip Code', 'Network'], zone: 'Zip Code' }), mounted () { // 校验map实例是否就绪 if (this.map && typeof this.map.on === 'function') { this.initMapLogic() return } // 未就绪就监听map属性的变化,就绪后再执行初始化 const unwatch = this.$watch('map', (newMap) => { if (newMap && typeof newMap.on === 'function') { this.initMapLogic() unwatch() } }, { deep: true, immediate: true }) }, methods: { initMapLogic() { // 先判断地图是否已经加载完成,避免绑定失效的load事件 if (this.map.loaded()) { this.map.setLayoutProperty(this.layerIds[0], 'visibility', 'visible') this.map.setLayoutProperty(this.layerIds[1], 'visibility', 'none') } else { // 用once只绑定一次load事件,避免重复触发 this.map.once('load', () => { this.map.setLayoutProperty(this.layerIds[0], 'visibility', 'visible') this.map.setLayoutProperty(this.layerIds[1], 'visibility', 'none') }) } // 绑定鼠标移动事件 this.map.on('mousemove', (e) => { if( this.zone == 'Zip Code'){ const features = this.map.queryRenderedFeatures(e.point) // 原有后续逻辑 } }) } } }
2. 适配Nuxt SSR/SSG逻辑
把你的地图子组件重命名,增加.client.vue后缀,比如原名叫MapInteraction.vue就改成MapInteraction.client.vue,Nuxt会自动让该组件只在客户端渲染,完全跳过服务端渲染阶段,从根源避免Mapbox不兼容服务端的问题。
3. 修复manifest.js 404问题
如果没有用到PWA功能,直接删掉nuxt.config.js里的PWA相关配置即可;如果需要使用PWA,确认public目录下存在manifest.json文件,且配置路径正确。
内容的提问来源于stack exchange,提问作者JRT
相关产品推荐
相关产品推荐

