Skip to content

一、异步加载

1. 为什么选择异步加载

浏览器解析html文件时,从上向下解析构建DOM树。当解析到script标签时,会暂停DOM构建。先把脚本加载并执行完毕,才会继续向下解析。js脚本的存在会阻塞DOM解析,进而影响页面渲染速度。

2. 处理js脚本的常规操作

1. js和html混合在一起的场景

  • 将script标签放在html文件的底部,避免解析DOM时被阻塞。

2. js和html分开场景,js是单独的文件。

  • 方式一:利用HTML5新特性

    • async 和 defer 属性 注意:只适用于外部脚本

      javascript
      <script type="text/javascript" defer="defer" src="xxx.js"/>
    • 区别:

      两种属性用于异步加载脚本,都是采用并行下载,在下载的过程中不会产生阻塞。区别在于执行时机,async 是加载完成后立刻执行,defer 需要等待页面完成后执行。

  • 方式二:创建动态脚本元素

    • 动态创建script标签

    • 设置src属性,指向所需要加载的js路径

    • 加入head中,注意最好加入head中,因为加入body里面,可能会导致IE抛出一个操作已终止的错误信息。

      javascript
        const script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = 'xxxx.js';
        document.head.appendChild(script);

3. 百度地图api提供的加载方式

  • 方式一:demo演示,直接使用script标签

    javascript
    <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥">
    • 如果加载时遇到1 A parser-blocking, cross site (i.e. different eTLD+1) script,将api换成getscript即可。https://api.map.baidu.com/getscript?v=1.0&type=webgl&ak=您的密钥
  • 方式二:使用创建动态脚本元素方式

    javascript
    <script type="text/javascript"> 
    function initialize() { 
      var mp = new BMapGL.Map('map'); 
      mp.centerAndZoom(new BMapGL.Point(121.491, 31.233), 11); 
    } 
        
    function loadScript() { 
      var script = document.createElement("script"); 
      script.src = "https://api.map.baidu.com/api?v=1.0&type=webgl&ak=您的密钥&callback=initialize";
      document.head.appendChild(script); 
    } 
    window.onload = loadScript; 
    </script>

4. 加载百度地图示例

html
<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>异步加载</title>
    <style type="text/css">
        html {
            height: 100%
        }

        body {
            height: 100%;
            margin: 0px;
            padding: 0px
        }

        #container {
            height: 100%
        }
    </style>
</head>

<body>
    <div id="container" />
</body>
<script type="text/javascript">
    function initialize() {
        // 创建地图实例 
        var mp = new BMapGL.Map('container');
        // 初始化地图,设置中心点坐标和地图级别
        mp.centerAndZoom(new BMapGL.Point(121.491, 31.233), 11);
    }

    function loadScript() {
        var script = document.createElement("script");
        script.src = "https://api.map.baidu.com/api?v=1.0&type=webgl&ak=m24Wn3uhofXRWnkMgYLyGPY0LKCvKTkt&callback=initialize";
        document.head.appendChild(script);
    }
    window.onload = loadScript;
</script>

</html>

注意点:高度必须设置,否则会显示不出百度地图,如果设置的是100%,那就需要父节点加本身都是100%,如下:

html
<div class="container">
  <div id="map" />
</div>

5. 当百度api遇到vue

1. 组件式封装产生的问题

  • 场景:因为你的地图,不可能只是单纯的地图容器,地图下面还有其他的组件。

    html
    <template>
      <div class="container">
        <div class="map_container" ref="map_container" />
        <v-switch/>
      </div>
    </template>
  • 现象:即使你给所有的父组件的高度设置为100%,依旧无法显示地图

  • 解决方案:在map_container的class样式里加上绝对定位

    css
    .map_container {
      position: absolute;
      width: 100%;
      height: 100%;
    }

2. vue的异步加载

  • 新建bmapGL.js

    js
    const ak = 'xxx';
    
    /**
     * 异步加载百度地图
     * @returns { Promise }
     * @constructor
     */
    const loadBMapGL = () => new Promise((resolve, reject) => {
      window.init = async () => {
        resolve(window.BMapGL);
      };
      if (window.BMapGL) {
        return resolve(window.BMapGL)
      }
      const script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = `//api.map.baidu.com/api?v=1.0&type=webgl&ak=${ak}&callback=init`;
      script.onerror = reject;
      document.head.appendChild(script);
    });
    
    export default loadBMapGL
  • 在对应组件的生命周期函数mounted中调用

    js
    // 引入异步引入地图的方法
    import loadBMapGL from "@/utils/bmap";
    
    // 调用加载地图
    loadBMapGL().then(() => {
      // 初始化地图
    })

Released under the MIT License.