一個高性能的 Vue 高德地圖組件庫

爲何要開發這樣一個組件庫?

這個想法來源於以前開發的一個項目,該項目須要在 zoom 16 的級別下渲染 (100 * 100) 的小方格,使用高德地圖的多邊形覆蓋物 Polygon 進行渲染,在 mac 13 寸屏幕下渲染 1k+,在外接 27 寸(不太記得多少寸了)顯示屏下須要渲染近 3K 的覆蓋物。vue

我嘗試使用 vue-amap 這個組件庫,在 1k 覆蓋物的狀況下須要渲染 5 秒左右,在 3k 覆蓋物的渲染下會渲染 30+ 秒,甚至會讓瀏覽器直接崩潰。我選擇本身經過 AMap SDK 封裝了一個組件,然而性能比 vue-amap 還要差,1k 覆蓋物須要耗費 10+ 秒,若是我拿這個交給產品,他估計會打死我。git

這裏有一個渲染 2000 個覆蓋物 fast-amap 與 vue-amap 的對比,能夠感覺一下。github

FastAMap codepen.io/taoxusheng/…
VueAMap codepen.io/taoxusheng/…

爲何在 Vue 中使用高德 SDK 有明顯性能問題?

事實上,咱們在使用 Vue 開發的時候經過props將數據傳遞給組件或是data,而 Vue 默認會對這些數據進行deepWatch,而我放在 data 上的 Polygon 實例每次都會被 Vue 綁定,這就是形成性能下降的緣由。最後我本身封裝了一個 Polygon 的渲染類,1k+覆蓋物渲染在 1 秒左右,雖然解決了性能問題,但使用卻很不方便,由於在業務中有太多關於渲染處理的代碼,沒法作到只關心數據問題,須要編寫不少配置屬性。瀏覽器

FastAMap 是如何解決這個問題的?

在那個項目結束以後我就想封裝一個組件,然而卻一直有些問題困擾着我。異步

  1. 若是解決數據被 Vue 綁定的問題?
  2. 地圖加載多是異步的,若是保證使用子組件的時候地圖實例已經加載完成?
  3. 一個頁面中可能有多個地圖,以及多個地圖相關的子組件,子組件如何獲取地圖實例,以及如何保證他們的實例是正確的?

數據解耦

咱們經過 props 傳遞的數據都會被 Vue 綁定,但咱們能夠經過 clone 一份數據。在組件在 watch 數據,一旦數據變動就進行深 clone,而後實例經過 clone 數據去渲染。雖然 clone 會帶來一部分消耗,然而對比數據綁定的消耗幾乎微乎其微。函數

v-if slot

在地圖組件中添加一個boolean類型的值mapLoaded,當地圖加載完成以後纔去渲染子組件。這時候子組件的 mounted 函數中就能夠獲取到地圖實例。性能

圖實例註冊表

在 AMap 中封裝了一個地圖的註冊表類,當地圖建立成功後將實例添加進註冊表,銷燬後刪除註冊表中的實例。而全部的地圖組件都須要添加一個註冊表的 ID,這樣就能保證每一個組件都能獲取到其對應的地圖實例了。code

項目地址與文檔地址:

github: link.zhihu.com/?target=htt… 文檔: txs1992.github.io/fast-amap/開發

相關文章
相關標籤/搜索