搜尋

首頁  >  問答  >  主體

angular.js - AngularJS是不是不適合地圖類應用

看了AngularJS官網的一些例子,覺得很給力,將開發人員的注意力從滿屏的DOM操作中轉移到傳統的業務中,以數據為中心,綁定View,實現二者的綁定和更新。

自己平常做的較多的是地圖類應用,類似百度地圖PC版和騰訊地圖那種,考慮過用AngularJS,可是想來想去覺得不太合適,主要原因是地圖類應用一般依賴第三方地圖API ,例如基於百度地圖需要百度地圖Javascript API,騰訊也有自己的JS API,這些API的普遍概念是提供一個頁面元素,然後在這個元素裡創建一個可互動的地圖介面。

1 地圖初始化

假如我們希望在頁面p#map-p這個位置建立一個地圖,通常程式碼如下:

<p id="map-p"></p>

var map=new BMap.Map("map-p",{});

這個map物件有包含了許多方法例如添加疊加物、地圖繪製等,這些方法大多又會引起地圖介面的更新,例如下面的程式碼會在地圖介面上彈出一個視窗:

map.addInfoWindow();

如果按照AngularJS的裡面,我們應該在頁面裡聲明一個地圖的View,類似這樣

這樣的話,我們需要創建一個bd-mapdirective,意味著需要針對不同的地圖SDK建立不同的directive,雖然這個是一勞永逸的工作,算起來這個不算啥。

2 地圖互動

這一塊我覺得如果完全通過AngularJS封裝會導致把簡單問題複雜化,比如我從後台請求了10個酒店的數據markers,每個酒店有一個位置信息,一般情況下,我會這麼做:

for(var i......){
  var item=...
  var marker=new BMap.Marker(...);
  map.addOverlay(marker);
}

但是按照AngularJS的理念,markers明顯應該是某個scope裡面的數據,我們的業務應該關注在這個數據的獲取和更新上,界面的更新應該交由directive完成,於是我好像還需要創建marker對應的directive,到這一步驟我已經覺得有點複雜了,有一種多此一舉的感覺。

3 事件

地圖本身,以及地圖上面的疊加物多少都有一些事件的,比如你點擊了地圖,點擊了一個圖標等等,這些在地圖類應用裡面很常見,如果使用AngularjS的話好像又要封裝一下。

我的感覺是,地圖類SDK本身已經可以看作是一個MVC的實現,比如你把地圖的各種參數(數據)設置好,然後通過一句SDK提供的接口,一個地圖界面(View)就創建了,透過修改地圖中心點等接口,地圖視圖也跟著變化,這種情況下跟AngularJS強行結合好像會適得其反,這種情況我覺得還是Backbone更合適一點,畢竟Backbone的view還是比較靈活的,Model的渲染完全在自己手裡,可以手工操作dom,也可以呼叫透過地圖SDK完成,並沒有耦合的很緊密,不需要額外的工作。


學AngularJS時間比較短,大概1週,有這種想法,不知道有沒有哪裡理解不到位的地方?


補充,我覺得AngularJS最適合的場景是應用只需要原生的頁面元素的組合,比如不同的view只是將數據注入到不同的template的中,比如todolist,gmail這種,就是原生html元素的拼湊。

黄舟黄舟2749 天前790

全部回覆(5)我來回復

  • 大家讲道理

    大家讲道理2017-05-15 16:52:21

    首先,學 Angular 只有一週就能想到這麼深已經是很不容易了,比我當初強太多,我相信你能把 Angular 用的很好。

    其次,很遺憾我沒有怎麼接觸過地圖類應用,特別是不了解那些 SDK 究竟複雜到什麼程度,所以我很難說換用 Angular 是否能讓事情變得更好。

    先說句題外話,我覺得 API 和 SDK 是不同的,特別是對 webapp 來說。 API 通常是用於資料交換的,一般不會涉及到 DOM 物件;而 SDK 才是你說的那種,它們本身就有一套封裝好的邏輯,並且通常都提供了和 DOM 緊密耦合的介面呼叫。

    API 對於 Angular 來說可以處理得很好,自備的 Resource 特別適合用於封裝 API 服務。但 SDK 的話本身的封裝就比較完備了,在 Angular 的世界裡由於強調不直接操作 DOM 反而使得 SDK 的融入會變得複雜和困難一些。這個現象的確是存在的,解決之道也的確和你想的差不多,利用 directive 抽象 DOM 交互,利用 service 抽象邏輯部分。比如說想Highcharts 這樣的東東——雖然不是地圖SDK,但也是類似的較複雜且封裝完備的第三方庫——它與Angular 的整合就相當不容易,坑也不少,所以才會有很多人單獨做了Angular+Highcharts 的模組用於重用,你可以搜搜這方面的例子看看其實現大概能估量出是否合適了。

    Angular 的封裝是否會讓簡單問題複雜化?有時候是的。這其實取決於問題本身,Angular 也不是萬用藥,它並非適合所有類型的應用。你覺得 Backbone 完全能 handle 你現在的工作?那就繼續用,不用理會「潮流」。反之等你確實發現 Angular 有 Backbone 無法媲美的部分,那就果斷用 Angular 上手,反正沒有一個框架是完美的,該解決的問題只要你碰了就還得解決,不碰就沒有必要操心。

    另外我想延伸這個探討。

    讓我們把技術粗略的分為三個部分:過去的技術(或者說成熟的技術),眼下的技術(或者說流行的技術),以及未來的技術(或者說代表著趨勢的技術)。

    我們很容易衝動的決定用“眼下的技術”來替代“過去的技術”,大體上來說會有代價,但也絕對不會沒有好處,並且處理得當的話,好處總是勝於代價的。

    問題是「眼下的技術」總是有很多選擇,我們會比較容易陷入這種選擇中無法決斷,甚至會覺得退回到過去的技術似乎也沒有什麼大不了的,至少很安全。

    我沒辦法說怎樣是對的,最近一年回答了很多次這樣的問題,我自己都有些疲倦了,我只能說說自己的判斷。

    我傾向於透過學習和了解“未來的技術”來選擇“眼下的技術”,並堅決取代“過去的技術”。

    「過去的技術」總是會過去,遲與早不過是一個時間問題,我是那種「逆水行舟,不進則退」的類型,即使代價會大也在所不惜。

    「眼下的技術」是否與「未來的技術」合拍其實反映了作者/團隊對科技趨勢的理解和判斷,也反映了你個人的理解和判斷,這裡面會帶一點賭博的成分,有沒有這份自信和決斷能力就得看自己了。

    我為什麼談到「未來的技術」呢?就拿你做的地圖類應用來說吧,你覺得像現在的這些 SDK 還能用多久?不單單指它們的程式碼本身,而是它們的技術棧,基於 SDK 以 DOM 為導向的地圖類應用開發模式還能持續多久?

    如果你覺得這個問題很難回答,那麼第一可以回顧一下業界領頭羊們的發展歷史,比如 Google Maps;再一個去了解一下同行中領先者的技術架構。

    我們差不多都知道並且可以預期WebComponents 將會是webapp 的下一個big thing,那麼,當WebComponents 變成“眼下的技術”的時候(說不定用不了多久),現在的這套基於SDK 以DOM 為導向的地圖類應用開發模式還有多少進步空間與生存空間?

    我不知道答案,也不想灌輸給你什麼“價值觀”,我只是描述一下我會如何思考並如何決斷。透過你對問題的描述我感覺你並非只是一個程式設計師,說不定你在你的團隊裡也扮演者「架構師」一類的角色,所以我才多說這些,總的意思就是四個字:高瞻遠矚。

    回覆
    0
  • phpcn_u1582

    phpcn_u15822017-05-15 16:52:21

    感覺map部分不一定要跟angular扯上什麼關係,可以把地圖放在angular之外或是讓angular不去編譯map部分。但不影響你去使用正常的map(畢竟已經被他們封裝好了),在需要angular做處理的時候,再交由angular去處理。

    雖然你用了angular,但是不一定頁面上所有元素都要和angular相關,把它用在它擅長的地方的就可以了。不要為了用angular而去把所有東西都和angular掛鉤。

    回覆
    0
  • 滿天的星座

    滿天的星座2017-05-15 16:52:21

    本人之前做過一段時間的Openlayers開發,對Angularjs也有一些初步的認識

    這屬於兩個不同領域的框架
    地圖API專注於G的展現,AngularJS專注於IS的展現,兩者並不衝突.舉例
    當我們做查詢時,服務端返回一系列的要素資訊,現在一般的做法都是便利要素,獲取資訊,然後透過模板拼湊出HTML,顯示結果列表,同時,將這些要素資訊加入圖層,繪製到地圖上.

    地圖API幫我們完成了地理要素的繪製,但是資訊資料是需要我們自己來控制的.

    讓我們來模擬一段滑鼠和要素互動的例子

    function highlight(feature){
        map.control.select(feature)
    }
    

    //偽代碼(原始),或其他前端模板

    var i=0,l=arrs.length,str=[],$case,map;
    for(;i<l;i++){
        str.push("<li>"+arrs[i].name+"</li>")
    }
    $case.on("mouseenter","li",function(){
        var index=$(this).index();
        var feature=arrs[index];
        highlight(feature);
    })
    

    //AngularJS

    <li ng-repeat="item in arrs" ng-mouseenter="highlight(item)">{{item.name}}</li>
    

    當然,原始採用其他的js模板也可進行MVC,但是使用AngularJS的好處在於單頁應用,中間實現過程都只是條條大道通羅馬而已.

    但是,需求改變了,我們在高亮要素的同時,能夠高亮當前的li元素,或者其他的新需求,這時候就會發現,我們改動代碼的點不在一個位置

    原始方法需要在事件綁定的過程中增加樣式的切換

    //AngularJS

    <li ng-repeat="item in arrs" 
        ng-mouseenter="highlight(item);item.active=true"
        ng-mouseleave="item.active=false"
        ng-class="{'highlight':item.active}"
        >{{item.name}}</li>
    

    簡單來講,維護變的更快速,原有業務不受影響.

    回覆
    0
  • 仅有的幸福

    仅有的幸福2017-05-15 16:52:21

    的確,地圖SDK已經幫你完成了DOM的管理,這部分的工作和ng的重複了,所以再強加ng上去就會感覺怪怪的。如果地圖SDK的提供本身就是ng方式的那可能就會帶來不一樣的開發體驗了。

    回覆
    0
  • 漂亮男人

    漂亮男人2017-05-15 16:52:21

    剛開始覺得有點麻煩,不過逐漸理解angular就覺得比較順手了。
    要知道不管什麼JS框架,物件都是傳遞的參考。
    然後對於SDK,其實把SDK的物件綁到一個service上,注意在回調裡$apply一下就好了

    回覆
    0
  • 取消回覆