原文链接:
百度地图官网文档介绍使用JSSDK时,仅提供了2种引入方式:
- script引入
- 异步加载
但vue项目中仅某一两个页面需要用到百度地图,所以不想在 index.html
中全局引用。
那在单个vue组件页面中如何引入呢?
刚开始时,是直接通过 DOM 操作方式插入script标签到当前document中,如下:
let scriptNode = document.createElement("script");scriptNode.setAttribute("type", "text/javascript");scriptNode.setAttribute("src", "http://api.map.baidu.com/api?v=3.0&ak=您的密钥");document.body.appendChild(scriptNode);
结果是不行的。
然后考虑使用异步加载的方式,结合参考网上方案,单独创建baidu-map.js
脚本:
export default { init: function (){ const AK = "AK密钥"; const apiVersion = "3.0"; const timestamp = new Date().getTime(); const BMap_URL = "http://api.map.baidu.com/api?v="+ apiVersion +"&ak="+ AK +"&services=&t=" + timestamp; return new Promise((resolve, reject) => { // 插入script脚本 let scriptNode = document.createElement("script"); scriptNode.setAttribute("type", "text/javascript"); scriptNode.setAttribute("src", BMap_URL); document.body.appendChild(scriptNode); // 等待页面加载完毕回调 window.onload = function () { resolve(BMap) } }); }}// -------------------------// vue引入调用import BaiduMap from 'baidu-map';...mounted(){ BauduMap.init() .then((BMap) => { console.log(BMap) console.log("加载成功...") })}...
结果还是不行。
想了下原因,一、可能是vue中window.onload没有触发,二、百度地图JSSDK没有真正加载成功。
继续验证测试,发现window.onload能够正常触发,那就是JSSDK没有加载成功。
直接复制JSSDK URL浏览器中打开 ,关键点来了,打开后内容如下:
(function(){ window.BMap_loadScriptTime = (new Date).getTime(); document.write('');})();
从返回内容中看出,立即执行函数中再次插入了另外一个<scirpt>标签,经检查发现这个<scirpt>实际并没有插入成功。
既然如此,那就直接把脚本放到我们上面的代码中去加载,结果就真的成功了。
修改优化后的代码如下:
export default { init: function (){ console.log("初始化百度地图脚本..."); const AK = "AK密钥"; const apiVersion = "3.0"; const timestamp = new Date().getTime(); const BMap_URL = "http://api.map.baidu.com/getscript?v="+ apiVersion +"&ak="+ AK +"&services=&t=" + timestamp; return new Promise((resolve, reject) => { if(typeof BMap !== "undefined") { resolve(BMap); return true; } // 插入script脚本 let scriptNode = document.createElement("script"); scriptNode.setAttribute("type", "text/javascript"); scriptNode.setAttribute("src", BMap_URL); document.body.appendChild(scriptNode); // 等待页面加载完毕回调 let timeout = 0; let interval = setInterval(() => { // 超时10秒加载失败 if(timeout >= 20) { reject(); clearInterval(interval); console.error("百度地图脚本初始化失败..."); } // 加载成功 if(typeof BMap !== "undefined") { resolve(BMap); clearInterval(interval); console.log("百度地图脚本初始化成功..."); } timeout += 1; }, 500); }); }}
问题到此就解决了,至于为什么用官网提供的地址没有真正加载到JSSDK这个问题有空再研究下。
最新解决方案
export default { init: function (){ //console.log("初始化百度地图脚本..."); const AK = "AK密钥"; const BMap_URL = "https://api.map.baidu.com/api?v=2.0&ak="+ AK +"&s=1&callback=onBMapCallback"; return new Promise((resolve, reject) => { // 如果已加载直接返回 if(typeof BMap !== "undefined") { resolve(BMap); return true; } // 百度地图异步加载回调处理 window.onBMapCallback = function () { console.log("百度地图脚本初始化成功..."); resolve(BMap); }; // 插入script脚本 let scriptNode = document.createElement("script"); scriptNode.setAttribute("type", "text/javascript"); scriptNode.setAttribute("src", BMap_URL); document.body.appendChild(scriptNode); }); }}
优化如下:
- 直接使用官网提供的引用地址:
http://api.map.baidu.com/api?v=2.0&ak=您的密钥
- 启用
callback
参数,异步加载必须使用此参数才可以生效 - 启用
https
配置,通过s=1
参数实现 - API版本为
2.0
,经测试使用,发现3.0
版本在HTTPS环境下是有问题的,脚本内部某些请求固定使用HTTP,无法正常使用。