最近工作中需要使用百度api。一般情况在项目中 html文件中通过script标签引入就行了。但是,业务需求要求百度ak是动态加密的 ,就需要从接口获取了。
html文件中是不建议写js代码的,那怎么动态引入呢?我就在app.vue文件中再获取到ak后动态的在head中插入百度api脚本。
onMounted(() => {
// 获取百度地图ak接口
$api.apiLogin.authenticate({}).then((res)=>{map_scriprt(res);}).catch((err)=>{console.log(err) })
});
// 动态获取ak
const map_scriprt = (akValue)=>{
let head = document.querySelector('head') ;
let scriptNode = document.createElement('script');
let BMap_URL = `https://api.map.baidu.com/getscript?type=webgl&v=1.0&ak=${window.atob(akValue)}`;
// 插入script脚本
scriptNode.setAttribute('type', 'text/javascript');
scriptNode.setAttribute('src', BMap_URL);
head.appendChild(scriptNode);
}
然后在地图展示的页面进行百度地图实例挂载,然后,,,就报错了
onMounted(() => {
//getLocation 接口获取业务坐标信息
getLocation({}).then((res)=>{
mapOptin(res); // mapOptin 百度Map实例配置对象
})
});
看了下报错 是因为app.vue中的百度js脚本还没加载完,百度map的BMapGL对象还没生成,于是想到了将挂载百度实例异步执行,nextTick并且加了一个if判断(兜底操作)
onMounted(() => {
nextTick(()=>{
//getLocation 接口获取业务坐标信息
getLocation({}).then((res)=>{
if (window?.BMapGL) {
mapOptin(res); // mapOptin 百度Map实例配置对象
}
})
})
});
这样就好了。
但是。。。后面测试人员发现有bug!!! 就是项目国际化语言切换时候,重新加载页面会偶现地图空白并且控制台没有报错,因为是偶现没法复现,那是什么原因呢?使劲理下逻辑 ,断定还是挂载的百度实例对象有问题。就是BMapGL对象没有生成,mapOptin对象一直没有挂载,所以才是空白没报错(因为head标签里面已经有脚本了,并且控制台没有任何报错,而清除缓存后js加载速度受网限不同)。于是就用了一个图方法,设置个定时器,时间设置的很小用来轮询百度地图脚背加载状态,询问window中BMapGL对象是否生成,只要确保js加载成功、BMapGL对象生成了再进行配置项的白队实例对象挂载就行了。
上代码 解决
const timer = ref(null);
onMounted(() => {
timer.value = null;
nextTick(()=>{
getLocation({}).then((res)=>{
timer.value = setInterval(()=>{
if (window?.BMapGL) {
clearInterval(timer.value);
mapOptin(res);
}
},300)
})
})