前言

最近在优化之前写的网站,FP 大概要半分钟才能加载出来,emmm,我写的。。。

这个也是之前文章优化的一部分,因为我的网页中有用到地图,之前用的 vue-amap 组件,后来觉得这个引用 cdn 不知道怎么下手,就改成了直接用节点渲染,不用组件了。然后又查了异步加载的方式,发现了一个解决方案,但是后期又发现了这个解决方案的一些 bug,一通百度加自己尝试修改了一下。

正文

先贴一下原文的解决方案:

1. 创建一个 AMap.js,路径’src/assets/js/AMap.js'

// src/assets/js/AMap.js

export default function MapLoader() {
  // <-- 原作者这里使用的是module.exports
  return new Promise((resolve, reject) => {
    if (window.AMap) {
      resolve(window.AMap)
    } else {
      var script = document.createElement('script')
      script.type = 'text/javascript'
      script.async = true
      script.src =
        'http://webapi.amap.com/maps?v=1.3&callback=initAMap&key=yourkey'
      script.onerror = reject
      document.head.appendChild(script)
    }
    window.initAMap = () => {
      resolve(window.AMap)
    }
  })
}

2. 在任何.vue 文件中使用

// test.vue
<template>
  <div class="test">
    <div id="container" class="h300 w300"></div>
  </div>
</template>
<script>
import MapLoader from '@/assets/js/AMap.js'
export default {
  name: 'test',
  data() {
    return {
      map: null,
    }
  },
  mounted() {
    let that = this
    MapLoader().then(
      (AMap) => {
        console.log('地图加载成功')
        that.map = new AMap.Map('container', {
          center: [117.000923, 36.675807],
          zoom: 11,
        })
      },
      (e) => {
        console.log('地图加载失败', e)
      }
    )
  },
}
</script>

遇到的问题

  1. 我 copy 代码之后,回调函数中获取不到 AMap。 不清楚 window.init 这个事件或是函数是什么意思。这里参考文档给出的异步加载方案,其中有用到 window.init ,我在网页中打印 window 并没有 init 这个属性,这里是不是还需要再进行调用? 然后,我就将 window.init 修改为 window.onload,等 js 资源加载完成后再将 AMap 对象返回给回调函数。然后就能获取到了。 等我后来调试的时候,又遇到了 bug2 号。
  2. 若首次打开的页面不包含加载了地图的组件,经路由跳转后追加的脚本,回调函数也拿不到 AMap 对象。 因为 window.onload 只在首次页面资源加载完成后调用。vue 切换路由只是切换了节点中的内容,并未刷新页面。所以追加了 script 标签后,并不会再执行 window.onload 了,就拿不到脚本解析后 AMap 对象了。 恰好我上午看到了相关内容就又做了修改,将 window.onload 替换为 script.onload (意思为脚本资源加载完成),目前暂时解决问题了。 load 的文档。

参考文献

(ps: 点击文献都可以直达文章)

  • load MDN

    load 事件: 当一个资源及其依赖资源已完成加载时,将触发 load 事件。

  • window 的 onload 事件和 domcontentloaded 执行顺序

    onload 事件支持

    我们首先来看一下都有哪些支持onload事件。

    • 支持该事件的 HTML 标签:<body>, <frame>, <frameset>, <iframe>, <img>, <link>, <script>;
    • 支持该事件的 JavaScript 对象:image, layer, window
  • JavaScript 判断图片是否加载完成的三种方式

    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="utf-8">
        <title>img - load event</title>
    </head>
    <body>
        <img id="img1" src="http://pic1.win4000.com/wallpaper/f/51c3bb99a21ea.jpg">
        <p id="p1">loading...</p>
        <script type="text/javascript">
            img1.onload = function() {
                p1.innerHTML = 'loaded'
            }
        </script>
    </body>
    </html>
    

以上。😆