更新:

2022.6.9
用高德地图也出现类似问题,定位到了原因,看另一篇
vue 使用高德地图、腾讯地图 实例化对象报错或地图异常


最近在项目中用到腾讯地图点标记功能(MultiMarker)。

发现在更新点数据的时候发生报错,怀疑是Vue的响应代理导致的。
Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': [object Object] could not be cloned.

已发现受影响的方法

  • setGeometries()
  • updateGeometries()
  • add()

不知道是不是我写法的问题?
网上没找到解决办法,摸索出了一个方案,支持vue 2.x和vue 3.x,见下文。
在这里插入图片描述

版本

腾讯位置服务:JavaScript API GL
Vue:2.x, 3.x

上代码

vue 2.x 选项式API

会报错的写法

<script>
export default {
  data () {
    return {
      TMap: null, // 腾讯地图工具类实例
      map: null, // 地图实例
      marker: null, // 标注点图层实例
    }
  },
  async mounted() {
    await this.initMap()
    this.initMarker()
    setTimeout(() => {
      this.updateMarker()
    }, 3000)
  },
  methods: {
    initMap () {
      // 创建工具类和地图实例,存入变量中
      ...
    },
    initMarker () {
      // 创建标注点图层存入变量
      // 构建实例代码相同,以下不再重复
      const { TMap, map } = this
      this.marker = new TMap.MultiMarker({
        map,
        styles: {
          start: new TMap.MarkerStyle({
            width: 25,
            height: 35,
            anchor: { x: 16, y: 32 },
            src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/start.png',
          })
        },
        geometries: [
          {
            id: 'start',
            styleId: 'start',
            position: new TMap.LatLng(39.98481500648338, 116.30571126937866),
          }
        ],
      })
    },
    updateMarker () {
      // 在这里用就会报错(已经不是最初的TA了)
      this.marker.updateGeometries([
        {
          id: 'start',
          styleId: 'start',
          position: new TMap.LatLng(39.982348784165886, 116.3111400604248),
        }
      ])
    }
  }
}
</script>

改一下 updateGeometries() 的位置,就能正常使用

methods: {
	initMarker () {
		// 创建标注点图层存入变量
		const { TMap, map } = this
		const marker = new TMap.MultiMarker({...
		})
		this.marker = marker
		// 在这里可以成功更新标注点
		marker.updateGeometries([
		  {
		    id: 'start',
		    styleId: 'start',
		    position: new TMap.LatLng(39.982348784165886, 116.3111400604248),
		  }
		])
	}
}

因此怀疑是受Vue响应代理影响,把实例变量放到外面试试,果然成功了。

正常使用的写法

<script>
// * 存放实例的变量放到外面来
let TMap, map, marker
export default {
  async mounted() {
    await this.initMap()
    this.initMarker()
    setTimeout(() => {
      this.updateMarker()
    }, 3000)
  },
  methods: {
    initMap () {
      // 创建工具类和地图实例,存入变量
      ...
    },
    initMarker () {
      // 创建标注点图层,存入变量
      marker = new TMap.MultiMarker({...
      })
    },
    updateMarker () {
      // 现在可以成功更新标注点
      marker.updateGeometries([
        {
          id: 'start',
          styleId: 'start',
          position: new TMap.LatLng(39.982348784165886, 116.3111400604248),
        }
      ])
    }
  }
}
</script>

vue 3.x 组合式API(setup)

与选项式相同,受响应代理影响的实例无法使用某些方法。

会报错的写法

<script setup>
import { ref, onMounted } from 'vue'
let TMap, map
const marker = ref(null)

onMounted(async () => {
  await initMap()
  initMarker()
  setTimeout(() => {
    updateMarker()
  }, 3000)
})

const initMarker = () {
  // 创建标注点图层,存入变量
  marker.value = new TMap.MultiMarker({...
  })
}

// 其余代码相同
const updateMarker = () => {
  // 这样写会导致报错
  marker.value.updateGeometries([
    {
      id: 'start',
      styleId: 'start',
      position: new TMap.LatLng(39.982348784165886, 116.3111400604248),
    }
  ])
}
</script>

正常使用的写法

<script setup>
import { onMounted } from 'vue'

// * 存放实例的变量放到外面来
let TMap, map, marker

const initMap = async () => {
  // 创建工具类和地图实例,存入变量中
  ...
}

const initMarker = () {
  // 创建标注点图层,存入变量
  marker = new TMap.MultiMarker({...
  })
}

const updateMarker = () => {
  // 可以成功更新标注点
  marker.updateGeometries([
    {
      id: 'start',
      styleId: 'start',
      position: new TMap.LatLng(39.982348784165886, 116.3111400604248),
    }
  ])
}
</script>

完成。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐