AngularJS和jquery,有什麼區別?
AngularJs 與Jquery的對比分析,超詳細!
閑來無事,在網上發現了一篇對比AngularJs和Jquery的文章.恰好最近自己也在研究AngularJs.特此收藏.需要的朋友可以參考.
原問題:假如我熟悉利用jQuery去開發客戶端應用,那麼我怎麼上手angularjs,能否描述下所需要的模式轉變,下面這些問題能夠幫助你給出一個回答:
1.在設計客戶端web應用的時候有什麼區別,最大的區別是什麼?
2.我應該停止使用哪些技術,同時又使用哪些技術作為替代?
3.是否存在服務端需要考慮的東西或者說一些限制呢?
回答:
1.不要首先設計好你的頁面,然後再通過DOM操作去修改它
在jQuery中,你首先設計了一個page,然後再去動態修改它的內容,這是因為jQuery被設計用來進行擴展並在這個前提下大幅度地增加和修改內容,但是在angularjs中,你必須在心中先設計好你的架構,
從一開始,你就要摒棄「我擁有一個DOM元素並且想讓它去做某件事」,代之為「我需要完成什麼任務,然後接著設計你的應用,最後再去設計你的視圖view層」。
2.不要使用angularjs去擴展jQuery
相應地,不要存在說讓jQuery去干某些事情,然後在此基礎上添加angularjs的功能讓它去管理model以及controller的想法。所以我一般不推薦AngularJS開發新手同時使用jQuery,至少在他們還沒有適應AngularJS的開發模式之前不會去推薦這樣做,但是當你真正開始適應angularjs 的方式之後,你會發覺這是一件很誘人的事情。
我曾經看到過很多開發者採用將150到200行代碼的jQuery插件利用angularjs的回調以及$apply方法封裝起來,這種方式使得代碼看起來極其複雜,但是實際上他們讓這些插件跑起來了!問題在於,在大部分情況下jQuery插件能夠用angularjs進行重寫,並且可能只會使用很少量的代碼,同時這種重寫使得代碼很直觀且易於理解,這顯然好過於將jQuery代碼直接做封裝。
所以最後說,當你遇見問題的時候,首先要以angularjs的思維進行思考,如果找不到解決方案,可以求助於社區,如果說沒有人能夠給出一個簡單的方案,那麼才考慮使用jQuery,不要讓jQuery成為你的拐杖,否則你永遠掌握不了AngularJS。
3.要以架構為中心進行思考
首先你要知道單頁應用屬於web應用,它們不是傳統的多網頁網站,所以我們要同時作為一個服務端和客戶端開發者的思維進行思考,我們需要思考如何將我們的應用分為獨立的,可擴展的以及可測試的部分。
那麼接下來我們如何採用AngularJS思維去工作呢,以下是一些將其與jQuery對比之後的基本準則:
以下是某個應用的視圖層:
在jQuery中,我們動態地去修改這個視圖,我們使用ul去定義一個dropdown menu
複製代碼代碼如下:<ul class="main-menu"> <li class="active"> <a href="#/home">Home</a> </li> <li> <a href="#/menu1">Menu 1</a> <ul> <li><a href="#/sm1">Submenu 1</a></li> <li><a href="#/sm2">Submenu 2</a></li> <li><a href="#/sm3">Submenu 3</a></li> </ul> </li> <li> <a href="#/home">Menu 2</a> </li></ul>在jQuery中,我們採用如下邏輯使用這個dropdownMenu
複製代碼代碼如下:$(".main-menu").dropdownMenu();讓我們回頭看看這個view,你會發現它的功能並不是很直白,對於小型應用來講,這樣是可以的,但是對於大型應用來講,這種方式會讓人費解並且難以維護;
在angularjs中,這個視圖實際上是一項基於視圖的功能,我們可以這樣來定義ul
複製代碼代碼如下:<ul class="main-menu" dropdown-menu> ...</ul>這兩種方式實際上做了同樣的事情,但是在AngularJS方式下任何人看到這個視圖模板就知道接下來要幹什麼。無論何時當一個新成員加入開發團隊之後他都能夠看到這裡並發現這裡有一個叫做dropdownMenu的指令去操作view,他不需要去猜想正確的答案或者審查其他的代碼,這個視圖就直接告訴我們它要做什麼,相比於jQuery,它更為簡潔。
常常有些AngularJS新手問這樣的問題:我怎麼才能找到某個確切類型的所有link並在此基礎上添加一個directive,但是當我們回答了「你不應該這樣去做,你這是一種半jQuery半angularjs的想法」時,他們會覺得很吃驚。
問題在於他們試圖在AngularJS背景下用jQuery去做某件事,這通常不是一種好的方式,在指令之外你不需要去做任何dom操作,而指令是直接內添加在視圖上的,所以意圖已經很明顯了。記住,不要先設計好之後再去修改,而是先有架構然後在這個框架下再去設計。
數據綁定
這是到目前為止AngularJS最令人矚目的特性了,在數據綁定方面它捨棄了對DOM的操作方式,而這一切都是由AngularJS來自動更新視圖,你不必寫操作dom的代碼,在jQuery中,我們常常按照以下方式響應事件並修改視圖:
複製代碼代碼如下:$.ajax({ url: "/myEndpoint.json", success: function ( data, status ) { $("ul#log").append("<li>Data Received!</li>"); }});相對於這樣一個視圖
複製代碼代碼如下:<ul class="messages" id="log"></ul>除了混雜的問題之外,我們還存在我之前提到的如何表明自己意圖的問題。但是更為重要的是,我們必須人工手動去引用並更新這個DOM節點,如果我們想刪除其中一條,那麼必須以編程方式去操作那個DOM元素,那麼在這種情況下我們怎麼去測試DOM節點之外的邏輯呢,亦或者我們想改變展示方式呢?
以上代碼顯得凌亂又脆弱,但是在AngularJS中,我們可以這樣做:
複製代碼代碼如下:$http( "/myEndpoint.json" ).then( function ( response ) { $scope.log.push( { msg: "Data Received!" } );});我們的視圖應該像下面這樣
複製代碼代碼如下:<ul class="messages"> <li ng-repeat="entry in log">{{ entry.msg }}</li></ul>在那種情況下,我們的視圖也可以這樣
複製代碼代碼如下:<div class="messages"> <div class="alert" ng-repeat="entry in log"> {{ entry.msg }} </div></div>現在我們不使用ul,而是使用Bootstrap的彈出框,但是我們不用修改controller中的代碼,更為重要的是,不管是數據如何修改,視圖層也會自動隨之發生變化,非常簡潔!
儘管我這裡不會做演示,但是你需要知道數據綁定是雙向的,你可以編輯數據通過添加指令<input ng-model="entry.msg" />,此外還有很多其他的令人興奮的地方。
區別model層
在jQuery中,DOM類似於一種model,但是在AngularJS中,我們擁有不同於jQuery中的model層以便我們可以以任何我們想要的方式去管理它,它是完全獨立於視圖之外的。這種方式是有助於我們進行數據綁定並且可以保持對分離的關注,而且可以具備更好的可測試性。
關注點分離
以上所講都和這個總體的話題相關:讓你關注分離,你的視圖層顯示記錄,你的model層代表數據,你還有個服務層用來執行這些可復用的任務。你使用directive來執行dom操作並擴展你的視圖,並將它和controller連接起來,這也就是我在其他方面提到的有關於增強可測試性的原因。
依賴注入
幫助我們解決關注點分離的是依賴注入(DI),如果你是一個服務端開發者(Java或者PHP),你可能已經很熟悉這個概念了,但是如果你是從事客戶端開發的,你會覺得這個概念可能有些多餘和純屬追求時髦,但是實際上不是這樣。
從廣義的角度講,DI意味著你可以自由地聲明組件然後從這些組件中進行實例化,這是理所當然的。你不必知道載入順序,文件位置等諸如此類的事情,這種魔力不是能夠立即看到,但是我會給出一個例子:測試。
我們說在應用中,我們需要一個依賴於應用狀態和本地存儲的服務用來通過一個rest API來執行服務端存儲,當我們測試我們的controller時,我們不必和服務端進行通信,畢竟只是在測試controller而已。我們僅添加一個與我們最初組件相同的mock服務,注入器能夠確保我們的controller獲得一個虛擬的服務,controller自身不必也不需要了解這種差異。
那麼說說測試吧。
4.以測試驅動的開發
這部分是一個架構的第三部分,但是他是很重要的,以至於我需要將它放在最重要的位置。
在我們所有見過的,用過的以及寫過的jQuery插件中,有多少具有一套測試組件呢?其實並不多,這是因為jQuery在測試上不易控制,但是AngularJS卻與此不同。
在jQuery中,測試的唯一方法是使用一個demo頁去創建一個獨立組件來使得我們的測試可以執行dom操作。我們接下來我們必須開發一個獨立的組件然後將它集成到我們的應用中來,這是多不方便啊!在很多情況下,當我們使用jQuery開發實際上是做了很多重複開發而不是以測試驅動的開發,這又能怪我們嗎?
但是在AngularJS中我們可以關注分離點,所以我們可以做一些測試驅動的開發。例如,我們有一個directive用來說明在menu中我們的當前路徑,我們可以在視圖中這樣聲明:
複製代碼代碼如下:<a href="/hello" when-active>Hello</a>好了,現在我們可以寫一個測試用來測試這個不存在的指令when-active了
複製代碼代碼如下:it( "should add "active" when the route changes", inject(function() { var elm = $compile( "<a href="/hello" when-active>Hello</a>" )( $scope ); $location.path("/not-matching"); expect( elm.hasClass("active") ).toBeFalsey(); $location.path( "/hello" ); expect( elm.hasClass("active") ).toBeTruthy();}));我們直接run測試用例,你會發現是失敗的,這時候需要創建這個指令,如下:
複製代碼代碼如下:.directive( "whenActive", function ( $location ) { return { scope: true, link: function ( scope, element, attrs ) { scope.$on( "$routeChangeSuccess", function () { if ( $location.path() == element.attr( "href" ) ) { element.addClass( "active" ); } else { element.removeClass( "active" ); } }); } };});再次run這個測試用例,你會發現通過了並且菜單如請求的樣子顯示,我們的開發是兼有反覆性和可測試性,非常酷吧!
5.從概念上講,指令不是打包的jQuery
你常常聽說,dom操作只能在指令中,這是必須的,你必須嚴肅對待。
讓我們深入討論,
某些指令僅僅是裝飾我們的視圖(例如ngClass),因此有時候直接操作dom是可以的,但是當一個指令類似於一個小物件並且擁有自己的模板,那麼它應該當做一個分離的關注點,這就是說,它的模板需要和link中的執行邏輯以及其他controller函數分離開。
AngularJS擁有一整套的工具可以是這種分離更簡單,使用ngClass指令,我們可以動態地更新class,使用ngBind我們可以進行雙向數據綁定,使用ngShow和ngHide 我們
可以採用編程的形式顯示和隱藏一個元素,也包括我們自己寫的很多指令。換句話說,我們可以不用Dom操作而完成所有工作,dom操作越少,指令越容易測試,越容易指定他們的style屬性,就越容易在將來改變他們,那麼他們就越容易復用和分發。
我看過很多AngularJS新手使用指令封裝一大串 jQuery代碼,換句話說,既然我不能在controller裡面進行dom操作,那麼我可以將他放在指令中,雖然這相對於直接操作dom好很多,但是任然是錯誤的。
看看我們在上面的記錄,即使我們將其放在一個指令中,我們任然需要以Angular的方式去操作它,這種方式不執行dom操作!在很多時候dom操作是需要的,但是這種情況比你想的要少得多。當我們需要做dom操作的時候先問問自己這裡是否必須這樣做,這才是一種更好的方式。
下面是一個簡單的例子用來表明我常常見到的一種模式,我們需要I一個可切換的button:
複製代碼代碼如下:.directive( "myDirective", function () { return { template: "<a class="btn">Toggle me!</a>", link: function ( scope, element, attrs ) { var on = false; $(element).click( function () { on = !on; $(element).toggleClass("active", on); }); } };});在以上例子中存在以下錯誤:
1.首先,jQuery是不必要的,這裡的工作完全不需要jQuery!
2.第二,即使我們已經在頁面中引入了jquery,但是我們沒有理由去使用它,我們可以使用angular.element而我們的組件也能夠運行,即使這個項目中沒有引入jQuery。
3.第三,假設jquery是需要的在我們的指令中,我們可以使用jqLite去進行替代,只要引入jQuery即可,所以我們不必使用$而是使用angular.element;
4.第四,和第三點聯繫很緊密,jqLite元素不必使用$包裹起來,element元素傳遞到link函數中已經是一個jQuery對象了;
5.第五,我們之前已經說過,為什麼不將我們的模板和邏輯混合起來呢?
以上指令可以按照如下方式來重寫,即使在最複雜的情況下看起來也如此簡單。
複製代碼代碼如下:.directive( "myDirective", function () { return { scope: true, template: "<a class="btn" ng-class="{active: on}" ng-click="toggle()">Toggle me!</a>", link: function ( scope, element, attrs ) { scope.on = false; scope.toggle = function () { scope.on = !scope.on; }; } };});模板元素是在 template屬性中,你可以很容易替換掉它的style,而邏輯根本不用發生變化,達到了完全復用!
還有其他的好處,比如測試起來很簡單,不管模板裡面是什麼,指令API都不會發生改變,所以重構它很簡單。你可以隨意多次改變你的模板而不用改變指令,無論你怎麼改變,你的測試總能通過!
所以說指令不是一堆jQuery代碼的集合,比如函數等,而是HTML代碼的擴展,如果HTML代碼不能實現你需要的功能,你可以寫一個指令去實現它,然後像使用HTML那樣去使用它。
以另外一種方式講,AngularJS如果不做額外的事情,想想我們怎麼能夠使用ngClick,ngClass指令呢?
可以說AngularJs與Jquery的優勢乃至設計思路各有不同,按照我的理解.前者是先搭好房屋,再等人入駐.而後者是,需要入駐的人,帶著磚瓦自己來修一棟樓.至於哪一種更方便更適合你,因人而異了.
前面很多人也說了,jquery是一個類庫,是很多方法和函數的集合,而angular是一個框架,一個完整的前端項目開發的解決方案,它包括了視圖、數據操作等一系列。
用一個簡單的比喻來說明,開發一個項目就如造一把椅子,jquery就如同工具箱,裡面有扳手,有鎚子,釘子,電鑽等,它提供了很多更快造椅子的工具,而jquery的一些插件就像已經做好的椅子面或者椅子腿;而angular就如一個3d印表機或者一個加工廠,你提供原材料,它輸出凳子,具體裡面的實現方式,你無需關心。
在公司,我以前一直對新人都說,在使用angular時,一定要拋棄jquery的思維。他們在開發模式中有什麼區別?jquery主要操作dom,是基於界面視圖驅動的,所以在開發時候,是根據界面元素去賦值或者獲取數據,動態添加各種操作。而angular是數據驅動的,有數據,才有相應的界面和視圖,你不需要關心數據的存取。
有很多人剛開始接觸angular時,很難適應這種方式,會發現在代碼中,尤其在需要數據的時候,還是有很多獲取元素,然後取它的value的操作。很多只是套了angular的架子,裡面操作仍然使用jquery的用法。
但是也不是說angular就完全由於jquery,這個得看使用場景和項目,如果對於單頁面應用,就可以使用angular,它提供了一整套的方案,如路由,模塊化,服務等等。但是如果是多頁面項目,頁面之間關聯性很低,而且每個頁面功能比較單一,就可以使用jquery。
而且由於angular關注的是數據,jquery關注的是界面dom,所以在做一些交互性很強的項目時,jquery就更具有優勢。比如你需要做一個官網,裡面只有很少的數據相關的操作,更多的是界面操作,此時,jquery就更優於angular;如果你是做一個後台管理系統,這種更多的是關注數據的正確性,而交互性更低,此時,angular是更好的選擇。
另外,從學習成本來說,jquery更容易上手,所以很適合新人,angular學習坡度很大,更適合後續技能提升。
說這個區別可就大了去了。jquery可以算是js的一個工具庫。angularjs是基於mvvc模式的模塊化工具。從兼容性來說jquery可以兼容很古老的瀏覽器,angularjs不知道能兼容多少。從使用的廣泛性來說,jquery絕對要比angularjs使用範圍更廣。
推薦閱讀:
※如何看待一代冰箱巨頭新飛停產?
※有比豬八戒還垃圾的互聯網公司嗎?
※華為任正非「對人講灰度,對事講流程」,說的是什麼意思?
※外貿建站選擇國外開發的平台好還是國內的比較好?