# 介绍

> Fast AMap 是一个基于高德地图封装的一个高性能 Vue 组件库

## 为什么在 Vue 中使用高德 SDK 有明显性能问题？

这个想法来源于之前开发的一个项目，该项目需要在 zoom 16 的级别下渲染 (100 \* 100) 的小方格，使用高德地图的多边形覆盖物 Polygon 进行渲染，在 mac 13 寸屏幕下渲染 `1k+`，在外接 27 寸(不太记得多少寸了)显示屏下需要渲染近 `3K` 的覆盖物。

我尝试使用 vue-amap 这个组件库，在 `1k` 覆盖物的情况下需要渲染 5 秒左右，在 `3k` 覆盖物的渲染下会渲染 30+ 秒，甚至会让浏览器直接崩溃。我选择自己通过 AMap SDK 封装了一个组件，然而性能比 vue-amap 还要差，`1k` 覆盖物需要耗费 10+ 秒，如果我拿这个交给产品，他估计会打死我。

为什么会出现这种情况，事实上，我们在使用 Vue 开发的时候通过 `props` 将数据传递给组件或是 `data`，而 Vue 默认会对这些数据进行 `deepWatch`，而我放在 data 上的 Polygon 实例每次都会被 Vue 绑定，这就是造成性能降低的原因。最后我自己封装了一个 Polygon 的渲染类，`1k+` 覆盖物渲染在 1 秒左右，虽然解决了性能问题，但使用却很不方便，因为在业务中有太多关于渲染处理的代码，无法做到只关心数据问题，需要编写很多配置属性。

## Fast AMap 是如何解决这个问题的？

在那个项目结束之后我就想封装一个组件，然而却一直有些问题困扰着我。

1. 如果解决数据被 Vue 绑定的问题？
2. 地图加载可能是异步的，如果保证使用子组件的时候地图实例已经加载完成？
3. 一个页面中可能有多个地图，以及多个地图相关的子组件，子组件如何获取地图实例，以及如何保证他们的实例是正确的？

> 直到有一天脑袋灵光一闪，这些问题都迎刃而解。

#### 数据解耦

我们通过 props 传递的数据都会被 Vue 绑定，但我们可以通过 clone 一份数据。在组件在 watch 数据，一旦数据变更就进行深 clone，然后实例通过 clone 数据去渲染。虽然 clone 会带来一部分消耗，然而对比数据绑定的消耗几乎微乎其微。

#### v-if slot

我们在地图组件中添加一个 `boolean` 类型的值 `mapLoaded`，当地图加载完成之后才去渲染子组件。这时候子组件的 mounted 函数中就可以获取到地图实例。

#### 地图实例注册表

在 AMap 中封装了一个地图的注册表类，当地图创建成功后将实例添加进注册表，销毁后删除注册表中的实例。而所有的地图组件都需要添加一个注册表的 ID，这样就能保证每个组件都能获取到其对应的地图实例了。
