百度地圖官網文檔介紹使用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瀏覽器中打開 http://api.map.baidu.com/api?v=3.0&ak=您的密鑰 ,關鍵點來了,打開后內容如下:
(function(){
window.BMap_loadScriptTime = (new Date).getTime();
document.write('<script type="text/javascript" src="http://api.map.baidu.com/getscript?v=3.0&ak=您的密鑰&services=&t=20180102163224"></script>');
})();
從返回內容中看出,立即執行函數中再次插入了另外一個<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,無法正常使用。
