zoukankan      html  css  js  c++  java
  • 解决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 +"&amp;ak="+ AK +"&amp;services=&amp;t=" + timestamp;
        return new Promise((resolve, reject) =&gt; {
          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(() =&gt; {
            // 超时10秒加载失败
            if(timeout &gt;= 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&amp;ak="+ AK +"&amp;s=1&amp;callback=onBMapCallback";
        return new Promise((resolve, reject) =&gt; {
          // 如果已加载直接返回
          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,无法正常使用。

    原文地址:https://segmentfault.com/a/1190000012815739

  • 相关阅读:
    微信小程序~事件绑定和冒泡
    为promise增加abort功能
    Object构造函数的方法 之 Object.freeze
    ES6新特性:JavaScript中内置的延迟对象Promise
    js 预编译
    什么是PWA?PWA的发展趋势
    CSS隐藏元素的方法及区别
    网页编码:UTF-8、GB2312
    Mixin 和 CSS Guards
    css自定义checkbox样式
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9959714.html
Copyright © 2011-2022 走看看