31
原文链接:解决Vue引入百度地图JSSDK:BMap is undefined 问题

百度地图官网文档介绍使用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,无法正常使用。

WEI_HU
151 声望1 粉丝