【踩坑记】Vue2页面中渲染腾讯地图踩坑实录!

1,745 阅读1分钟

Vue2项目中如何接入腾讯地图,无需多说,参照官方文档,很好实现。今天我们要说的,是接入腾讯地图时踩的坑。

接入地图

我们项目中,接入地图的需求是,在新增/编辑活动时,根据用户输入的关键字进行地图定位,从而获取有经纬度坐标的活动举办地点,如下图:

image.png

为了实现该需求,写下了如下的伪代码:

<template>
  <div ref="mapWrap"style="width:100%;height:280px;" class="mapWrap"></div>  
</template>
       
<script>
    export default {
        data() {
            return {
                id: ''
                map: null, // 地图对象
                infoWindow: null, // 地图信息窗口对象
            }
        },
        activated() {
             const query = this.$route.query || {}
             this.id = query.id || ''
             if(this.id) {
               await this.getActivityDetail(this.id)
             }
            this.initMap()
        },
        methods: {
            initMap() {
               this.map = null
               this.infoWindow = null
               this.mapInit()
            },
            mapInit() {
               // 在获取DOM后操作
               this.$nextTick( () => {
                    if(!this.$refs.mapWrap) { // mapWrap获取不到时,往下走会报错 
                        return
                    }
                   // 按官方文档初始化地图
                   //...
                   
               })
            },
            // 获取活动详情
            getActivityDetail(id) {
                
            }
        }  
    }
</script>

没错,地图成功渲染出来了,但在自测过程中,一些隐形的坑也渐渐暴露出来了。

坑一:地图多次渲染

在自测过程中,交替打开新增页面、编辑页面(其实是同一个页面,入口不同而已),然后就出现了地图多次渲染的现象,如下图:

image.png

坑二:地图保留了上次操作的痕迹

在自测过程中,还发现了,多次打开新增页面,地图信息窗口等都还保留了上次的操作痕迹,如下图。打开编辑页面时没有这个问题,因为地图信息窗口里的内容是根据接口数据进行回显的。

image.png

针对坑一、坑二,排查原因,得知是每打开一次页面,就会追加绘制一个地图,而不是覆盖原来绘制的地图。

所以解决方案是:利用v-if,清除上一个绘制的地图,重绘最新的地图。

然后就加了如下的代码:

<template>
  <div ref="mapWrap"style="width:100%;height:280px;" class="mapWrap" v-if="mapShow"></div>  
</template>
       
<script>
    export default {
        data() {
            return {
              // ...
              mapShow: false// 新增字段
            }
        },
        methods: {
            initMap() {
               this.mapShow = false // 新增代码
               // ...
            },
            mapInit() {
               // 在获取DOM后操作
               this.$nextTick( () => {
                   this.mapShow = true // 新增代码
                   //...
                   
               })
            },
            
        }  
    }
</script>

好嘛,地图彻底渲染不出来了,然后就形成了坑三。

坑三:粗暴v-if下地图不渲染

坑三图示如下:

image.png

出现坑三的原因是下面代码的拦截:

 if(!this.$refs.mapWrap) { // mapWrap获取不到时,往下走会报错
     return
 }

也就是说地图DOM获取不到时,是不能初始化地图的。为了保证成功初始化地图,又加了如下代码。

initMap() {
    // ...
    // 以下是改造的代码
    if(!this.$refs.mapWrap) {
       let timer = null
       timer = setInterval(() => {
           setTimeout(() => {
               this.mapInit()
           },200)
           if(this.$refs.mapWrap&&timer) {
               clearInterval(timer)
           }
        }, 300 ) 
     } else {
        setTimeout(() => {
           this.mapInit()
        },200)
     }
}

通过定时器的方式保证,页面始终在正确的方式下渲染地图。

至于在setInterval中又加了setTimeout是因为,即使this.$refs.mapWrap有了,如果立马初始化地图,也是有可能不成功的,会出现坑三图示中的报错。

以上,就是在页面中渲染地图而踩的坑。注意是页面,如果是在弹框中渲染地图,是没有上述坑的,因为在弹框的显隐中已经有v-if控制了。