高德地图异步加载AMap和AMapUI组件
一. 介绍
什么是异步加载:异步加载是和同步加载相对的组件加载方式。同步加载模式又称阻塞模式,在页面加载到该组件时会阻止浏览器的后续处理与后续解析,只有当前加载完成后才会进行下一步的操作。异步加载相反,异步加载模式又称非阻塞加载模式,浏览器在加载js的同时还会进行后续的页面加载。异步加载的方式通常有三种,此次我们主要采用动态创建script标签的方式异步引入高德API。
近期在做服务器定位的项目,有用到高德组件,但是高德地图比较大,同步引入的话导致页面加载变慢,此外,我的项目也不是单页面应用,还涉及到很多其他业务,异步引入高德API就比较有必要。
异步加载指的是为 JS API 指定加载的回调函数,在 JS API 的主体资源加载完毕之后,将自动调用该回调函数。回调函数应该声明在 JS API 入口文件引用之前,异步加载可以减少对其他脚本执行的阻塞。
二. 异步加载AMap组件
新创建一个aMap.js文件,一般会创建一个plugin文件夹,把这个js文件放到plugin文件夹下。这个文件只加载了AMap组件,需要AMapUI组件的去下一个。
封装了js文件,之后在需要加载地图的页面直接import就可以,这里还用到了一些Promise的知识(Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息),不清楚的朋友百度看看。
aMap.js
/*
* 异步创建script标签
*/
export default function MapLoader (key) {
return new Promise((resolve, reject) => {
if (window.AMap) {
resolve(window.AMap)
} else {
var script = document.createElement('script')
const key= '填你申请的key'
script.type = 'text/javascript'
script.async = true
script.src = 'http://webapi.amap.com/maps?v=1.3&callback=initAMap&key=' + key
script.onerror = reject
document.head.appendChild(script)
}
window.initAMap = () => {
resolve(window.AMap)
}
})
}
在需要加载组件的.vue文件中,在script标签中
import MapLoader from '@/plugin/aMap'
之后在mounted或者created中加载:
MapLoader().then(AMap => {
console.log('地图加载成功')
this.map = new AMap.Map("container", {
zoom: 17,
resizeEnable: true
})
// ....你的操作
}, e => {
console.log('地图加载失败' ,e)
})
三. 异步加载AMap和AMapUI组件
同时加载AMap组件和AMapUI组件
aMapUI.js:
/*
* 异步创建script标签
*/
export default function MapUILoader (key) {
const mp = new Promise((resolve, reject) => {
if (window.AMap) {
resolve(window.AMap)
} else {
var script = document.createElement('script')
const key= '填你申请的api'
script.type = 'text/javascript'
script.async = true
script.src = 'http://webapi.amap.com/maps?v=1.3&callback=initAMap&key=' + key
script.onerror = reject
document.head.appendChild(script)
}
window.initAMap = () => {
resolve(window.AMap)
}
})
const mpUI = new Promise((resolve, reject) => {
if (window.AMapUI) {
resolve(window.AMapUI)
} else {
var scriptUI = document.createElement('script')
scriptUI.type = 'text/javascript'
scriptUI.src = 'http://webapi.amap.com/ui/1.1/main.js?v=1.1.1'
scriptUI.onerror = reject
scriptUI.onload = function(su){
resolve(window.AMapUI)
};
document.head.appendChild(scriptUI)
}
})
return Promise.all([mp,mpUI])
.then(function (result) {
return result
}).catch(e=>{
console.log(e);})
}
需要加载组件的.vue文件,在created函数中加载:
MapUILoader().then(AMap => {
console.log("异步加载组件")
})
由于两个API加载都比较慢,有时候可能会出现AMapUI not defined这样的错误,我们需要延时加载1秒:
if (!window.AMapUI || !window.AMap){
// 延时加载
console.log("延时加载中")
setTimeout(() => {
// ...你的操作
}, 1000)
}
else{
//...你的操作
}
注:在项目的
文件中,需要声明全局变量AMap和AMapUI: