javascript 如果我有jQuery背景,“在AngularJS中思考”?




(12)

假設我熟悉在jQuery開發客戶端應用程序,但現在我想開始使用AngularJS 。 你能描述一下必要的範式轉變嗎? 以下是一些可能有助於您確定答案的問題:

  • 如何以不同方式構建和設計客戶端Web應用程序? 最大的區別是什麼?
  • 我應該停止做什麼/使用什麼; 我應該開始做什麼/使用什麼呢?
  • 有任何服務器端考慮因素/限制嗎?

我不是在尋找jQueryAngularJS之間的詳細比較。


這些是一些非常好的,但冗長的答案。

總結一下我的經歷:

  1. 控制器和提供者(服務,工廠等)用於修改數據模型,而不是HTML。
  2. HTML和指令定義佈局和與模型的綁定。
  3. 如果您需要在控制器之間共享數據,請創建服務或工廠 - 它們是在應用程序中共享的單例。
  4. 如果需要HTML小部件,請創建指令。
  5. 如果您有一些數據,現在正在嘗試更新HTML ...停止!更新模型,並確保您的HTML綁定到模型。

jQuery的

jQuery製作了一些可笑的長命令,比如getElementByHerpDerp簡短和跨瀏覽器。

AngularJS

AngularJS允許您創建自己的HTML標記/屬性,這些標記/屬性可以很好地處理動態Web應用程序(因為HTML是為靜態頁面設計的)。

編輯:

說“我有一個jQuery背景我如何在AngularJS中思考?” 就像說“我有一個HTML背景我如何在JavaScript中思考?” 您提出問題的事實表明您很可能不理解這兩種資源的基本目的。這就是為什麼我選擇通過簡單地指出基本區別來回答問題,而不是通過列表說“AngularJS使用指令,而jQuery使用CSS選擇器來創建一個jQuery對象來執行此操作等等......” 。這個問題不需要冗長的答案。

jQuery是一種使瀏覽器中的JavaScript編程更容易的方法。更短,跨瀏覽器的命令等

AngularJS擴展了HTML,因此您不必<div>為了創建應用程序而將所有地方放在一起。它使HTML實際上適用於應用程序而不是它的設計目標,即靜態的教育網頁。它使用JavaScript以迂迴的方式實現這一點,但從根本上說它是HTML的擴展,而不是JavaScript。


你能描述一下必要的範式轉變嗎?

勢在必行與陳述

使用jQuery,您可以一步一步地告訴DOM需要發生什麼。使用AngularJS您可以描述您想要的結果,但不能描述如何執行此操作。更多關於here。另外,請查看Mark Rajcok的答案。

如何以不同方式構建和設計客戶端Web應用程序?

AngularJS是一個使用MVC模式的完整客戶端框架(查看其圖形表示)。它非常注重關注點的分離。

最大的區別是什麼? 我應該停止做什麼/使用什麼; 我應該開始做什麼/使用呢?

jQuery是一個庫

AngularJS是一個漂亮的客戶端框架,高度可測試,它結合了許多很酷的東西,如MVC,依賴注入,數據綁定等等。

它側重於關注點和測試(單元測試和端到端測試)的分離,這有助於測試驅動的開發。

最好的方法是通過他們的精彩教程。你可以在幾個小時內完成這些步驟; 但是,如果你想掌握幕後的概念,它們包含了無數的參考資料以供進一步閱讀。

有任何服務器端考慮因素/限制嗎?

您可以在已經使用純jQuery的現有應用程序上使用它。但是,如果您想充分利用AngularJS功能,可以考慮使用RESTful方法對服務器端進行編碼。

這樣做將允許您利用他們的資源工廠,它創建服務器端RESTful API的抽象,並使服務器端調用(獲取,保存,刪除等)非常容易。


我發現這個問題很有意思,因為我第一次認真接觸JavaScript編程的是Node.js和AngularJS。我從來沒有學過jQuery,我想這是件好事,因為我不需要忘記任何事情。事實上,我主動避免jQuery解決方案來解決我的問題,而只是尋找一種“AngularJS方式”來解決它們。所以,我想我對這個問題的回答基本上歸結為“想像一個從未學過jQuery的人”,並避免任何直接合併jQuery的誘惑(顯然AngularJS在某種程度上在幕後使用它)。


作為一個JavaScript MV *初學者,純粹關注應用程序架構(而不是服務器/客戶端問題),我肯定會推薦以下資源(我很驚訝還沒有提到):JavaScript設計模式,作者:Addy Osmani ,作為不同JavaScript設計模式的介紹。本答案中使用的術語來自上面的鏈接文檔。我不打算在接受的答案中重複措辭。相反,這個答案鏈接到為AngularJS(和其他庫)提供動力的理論背景

像我一樣,你會很快意識到AngularJS(或者Ember.js,Durandal和其他MV *框架)是一個複雜的框架,它匯集了許多不同的JavaScript設計模式。

我發現它也更容易,以測試(1)天然的JavaScript代碼和(2)對於這些模式中的每一個更小的文庫分別潛水成一個全球框架之前。這使我能夠更好地理解框架所針對的哪些關鍵問題(因為您個人面臨問題)。

例如:

注意:這個列表不完整,也不是'最好的圖書館'; 它們恰好是我使用的庫。這些庫還包括更多模式,提到的模式只是它們的主要焦點或原始意圖。如果您覺得此列表中缺少某些內容,請在評論中提及,我將很樂意添加它。


勢在必行→陳述性

在jQuery中, 選擇器用於查找DOM元素,然後將事件處理程序綁定/註冊到它們。 當事件觸發時,執行(命令性)代碼以更新/更改DOM。

在AngularJS中,您需要考慮視圖而不是DOM元素。 視圖是包含AngularJS 指令的 (聲明性)HTML。 指令為我們幕後設置了事件處理程序,並為我們提供了動態數據綁定。 選擇器很少使用,因此對ID(以及某些類型的類)的需求大大減少。 視圖與模型相關 (通過範圍)。 視圖是模型的投影。 事件更改模型(即數據,範圍屬性)以及投影這些模型的視圖會“自動”更新。

在AngularJS中,考慮模型,而不是jQuery選擇的DOM元素來保存您的數據。 將視圖視為這些模型的投影,而不是註冊回調來操縱用戶看到的內容。

關注點分離

jQuery使用不引人注目的JavaScript - 行為(JavaScript)與結構(HTML)分離。

AngularJS使用控制器和指令(每個控制器和指令可以有自己的控制器和/或編譯和鏈接函數)來從視圖/結構(HTML)中刪除行為。 Angular還提供服務過濾器,以幫助分離/組織您的應用程序。

另請參見https://.com/a/14346528/215945

應用設計

設計AngularJS應用程序的一種方法:

  1. 想想你的模特。 為這些模型創建服務或您自己的JavaScript對象。
  2. 想想你想要如何展示你的模特 - 你的觀點。 為每個視圖創建HTML模板,使用必要的指令來獲取動態數據綁定。
  3. 將控制器連接到每個視圖(使用ng-view和routing,或ng-controller)。 讓控制器只查找/獲取視圖完成其工作所需的任何模型數據。 使控制器盡可能薄。

原型繼承

你可以在不知道JavaScript原型繼承如何工作的情況下使用jQuery做很多事情。 在開發AngularJS應用程序時,如果您對JavaScript繼承有很好的理解,就可以避免一些常見的陷阱。 推薦閱讀: AngularJS中範圍原型/原型繼承的細微差別是什麼?


AngularJS與jQuery

AngularJS和jQuery採用了截然不同的意識形態。 如果您來自jQuery,您可能會發現一些令人驚訝的差異。 Angular可能會讓你生氣。

這很正常,你應該堅持下去。 Angular值得。

差異很大(TLDR)

jQuery為您提供了一個工具包,用於選擇DOM的任意位並對其進行臨時更改。 你幾乎可以做任何你喜歡的事情。

相反,AngularJS為您提供了一個編譯器

這意味著AngularJS從上到下讀取您的整個DOM並將其視為代碼,就像編譯器的指令一樣。 當它遍歷DOM時,它會查找告訴AngularJS編譯器如何操作以及如何操作的特定指令 (編譯器指令)。 指令是充滿JavaScript的小對象,可以匹配屬性,標籤,類甚至註釋。

當Angular編譯器確定DOM的一部分與特定指令匹配時,它調用指令函數,向其傳遞DOM元素,任何屬性,當前$ scope(本地變量存儲)以及一些其他有用位。 這些屬性可能包含可由指令解釋的表達式,它告訴它如何渲染,以及何時應重繪自身。

然後,指令可以引入額外的Angular組件,例如控制器,服務等。編譯器底部出現的是一個完整形成的Web應用程序,已連線並準備就緒。

這意味著Angular是模板驅動的 。 您的模板驅動JavaScript,而不是相反。 這是角色的徹底顛倒,與我們過去10年左右寫的不引人注目的JavaScript完全相反。 這可能需要一些時間來適應。

如果這聽起來像是過度規範和限制,那麼事實就沒有什麼可以了。 由於AngularJS將您的HTML視為代碼,因此您可以在Web應用程序中獲得HTML級別的粒度 。 一切皆有可能,一旦你做出一些概念上的飛躍,大多數事情都會非常容易。

讓我們深入了解細節。

首先,Angular不會取代jQuery

Angular和jQuery做了不同的事情。 AngularJS為您提供了一組用於生成Web應用程序的工具。 jQuery主要為您提供修改DOM的工具。 如果您的頁面上存在jQuery,AngularJS將自動使用它。 如果不是,AngularJS附帶jQuery Lite,這是一個減少但仍然完美可用的jQuery版本。

Misko喜歡jQuery並且不反對你使用它。 但是,隨著您的進步,您會發現使用範圍,模板和指令的組合可以完成所有工作,並且您應該盡可能地選擇此工作流程,因為您的代碼將更加離散,更易於配置,以及更多角。

如果你確實使用jQuery,你不應該把它灑到這個地方。 AngularJS中DOM操作的正確位置是在一個指令中。 稍後會詳細介紹。

使用選擇器與聲明模板的不顯眼的JavaScript

jQuery通常不引人注意地應用。 您的JavaScript代碼鏈接在標題(或頁腳)中,這是它唯一提到的地方。 我們使用選擇器來挑選頁面的位並編寫插件來修改這些部分。

JavaScript處於控制之中。 HTML具有完全獨立的存在。 即使沒有JavaScript,您的HTML仍然是語義。 Onclick屬性是非常糟糕的做法。

您將注意到的關於AngularJS的第一件事就是自定義屬性無處不在 。 您的HTML將充滿ng屬性,這些屬性基本上是類固醇上的onClick屬性。 這些是指令(編譯器指令),並且是模板掛鉤到模型的主要方式之一。

當你第一次看到這個時,你很可能會把AngularJS寫成老式的侵入式JavaScript(就像我之前做的那樣)。 事實上,AngularJS不遵守這些規則。 在AngularJS中,您的HTML5是一個模板。 它由AngularJS編譯以生成您的網頁。

這是第一個很大的區別。 對於jQuery,您的網頁是一個要操縱的DOM。 對於AngularJS,您的HTML是要編譯的代碼。 AngularJS會讀入您的整個網頁,並使用其內置編譯器將其編譯成新的網頁。

你的模板應該是聲明性的; 通過閱讀它的含義應該很清楚。 我們使用有意義名稱的自定義屬性。 我們再次使用有意義的名稱組成新的HTML元素。 具有最少HTML知識且無編碼技能的設計人員可以閱讀您的AngularJS模板並了解它的作用。 他或她可以進行修改。 這是Angular的方式。

模板處於駕駛席位。

在開始使用AngularJS並運行教程時,我問自己的第一個問題是“我的代碼在哪裡?” 。 我沒有寫過JavaScript,但我有這些行為。 答案很明顯。 因為AngularJS編譯DOM,所以AngularJS將您的HTML視為代碼。 對於許多簡單的情況,只需編寫一個模板就可以了,讓AngularJS將它編譯成一個應用程序。

您的模板可以驅動您的應用 它被視為DSL 。 您編寫AngularJS組件,AngularJS將負責將它們拉入並根據模板結構在適當的時間提供它們。 這與標準MVC模式非常不同,其中模板僅用於輸出。

例如,它比Ruby on Rails更類似於XSLT

這是一種徹底的控制反轉,需要一些人習慣。

停止嘗試從JavaScript驅動您的應用程序。 讓模板驅動應用程序,讓AngularJS負責將組件連接在一起。 這也是Angular方式。

語義HTML與語義模型

使用jQuery,您的HTML頁面應包含具有語義意義的內容。 如果JavaScript(由用戶或搜索引擎)關閉,您的內容仍然可以訪問。

因為AngularJS將您的HTML頁面視為模板。 模板不應該是語義的,因為您的內容通常存儲在最終來自API的模型中。 AngularJS使用模型編譯DOM以生成語義Web頁面。

您的HTML源不再是語義,而是您的API和編譯的DOM是語義的。

在AngularJS中,意思是生活在模型中,HTML只是一個模板,僅供顯示。

在這一點上,你可能有各種關於SEO和可訪問性的問題,這是正確的。 這裡存在未解決的問題。 大多數屏幕閱讀器現在將解析JavaScript。 搜索引擎也可以索引AJAXed內容。 不過,您需要確保使用的是pushstate URL,並且您有一個不錯的站點地圖。 有關該問題的討論,請參見此處: https://.com/a/23245379/687677 : https://.com/a/23245379/687677

關注點分離(SOC)與MVC

關注點分離 (SOC)是一種在多年的Web開發中長大的模式,其原因有多種,包括SEO,可訪問性和瀏覽器不兼容性。 它看起來像這樣:

  1. HTML - 語義含義。 HTML應該是獨立的。
  2. CSS - 樣式,沒有CSS,頁面仍然可讀。
  3. JavaScript - 行為,沒有腳本,內容仍然存在。

同樣,AngularJS不遵守他們的規則。 一舉一動AngularJS取消了十年的智慧 ,而是實現了MVC模式,其中模板不再是語義,甚至不是一點點。

它看起來像這樣:

  1. 模型 - 您的模型包含您的語義數據。 模型通常是JSON對象。 模型作為名為$ scope的對象的屬性存在。 您還可以在$ scope上存儲方便的實用程序函數,然後模板可以訪問這些函數。
  2. 視圖 - 您的視圖以HTML格式編寫。 視圖通常不是語義的,因為您的數據存在於模型中。
  3. 控制器 - 您的控制器是一個JavaScript函數,它將視圖掛鉤到模型。 它的功能是初始化$ scope。 根據您的應用程序,您可能需要也可能不需要創建控制器。 您可以在頁面上擁有許多控制器。

MVC和SOC不在相同比例的兩端,它們位於完全不同的軸上。 SOC在AngularJS上下文中沒有任何意義。 你必須忘記它並繼續前進。

如果像我一樣,你經歷過瀏覽器大戰,你可能會覺得這個想法很冒犯。 我保證,克服它,它是值得的。

插件與指令

插件擴展了jQuery。 AngularJS指令擴展了瀏覽器的功能。

在jQuery中,我們通過向jQuery.prototype添加函數來定義插件。 然後我們通過選擇元素並在結果上調用插件將它們掛鉤到DOM中。 我們的想法是擴展jQuery的功能。

例如,如果您想在頁面上使用輪播,則可以定義無序的圖表列表,可能包含在nav元素中。 然後,您可以編寫一些jQuery來選擇頁面上的列表,並將其重新設置為具有超時的庫以執行滑動動畫。

在AngularJS中,我們定義了指令。 指令是一個返回JSON對象的函數。 該對象告訴AngularJS要查找哪些DOM元素,以及要對它們進行哪些更改。使用您發明的屬性或元素將指令掛鉤到模板。我們的想法是使用新的屬性和元素擴展HTML的功能。

AngularJS方法是擴展本機外觀HTML的功能。您應該編寫看起來像HTML的HTML,並使用自定義屬性和元素進行擴展。

如果你想要一個輪播,只需使用一個<carousel />元素,然後定義一個指令來拉入一個模板,並讓那個吸盤工作。

很多小指令與配置開關的大插件

jQuery的趨勢是編寫像燈箱這樣的大插件,然後我們通過傳遞大量的值和選項來配置。

這是AngularJS中的一個錯誤。

以下拉列表為例。在編寫下拉插件時,您可能會想要在單擊處理程序中進行編碼,也許是一個添加到V形圖中的功能,可以是向上或向下,也許更改展開元素的類,顯示隱藏菜單,所有有用的東西。

直到你想做一個小改動。

假設您有一個要懸停的菜單。那麼現在我們有一個問題。我們的插件已連接到我們的點擊處理程序,我們將需要添加一個配置選項,以使其在這種特定情況下的行為不同。

在AngularJS中,我們編寫較小的指令。我們的下拉指令非常小。它可能保持折疊狀態,並提供fold(),展開()或toggle()的方法。這些方法只會更新$ scope.menu.visible,它是一個保持狀態的布爾值。

現在在我們的模板中,我們可以將其連線:

<a ng-click="toggle()">Menu</a>
<ul ng-show="menu.visible">
  ...
</ul>

需要在mouseover上更新?

<a ng-mouseenter="unfold()" ng-mouseleave="fold()">Menu</a>
<ul ng-show="menu.visible">
  ...
</ul>

該模板驅動應用程序,因此我們獲得HTML級別的粒度。如果我們想要逐案例外,模板可以輕鬆實現。

結束與$範圍

JQuery插件是在閉包中創建的。在該關閉內保持隱私。您可以在該閉包內維護您的範圍鏈。您只能真正訪問由jQuery傳入插件的DOM節點集,以及在閉包中定義的任何局部變量以及您定義的任何全局變量。這意味著插件是完全自包含的。這是一件好事,但在創建整個應用程序時會受到限制。嘗試在動態頁面的各個部分之間傳遞數據變成了一件苦差事。

AngularJS有$ scope對象。這些是由AngularJS創建和維護的特殊對象,您可以在其中存儲模型。某些指令將生成一個新的$ scope,默認情況下,它使用JavaScript原型繼承繼承其包裝$ scope。$ scope對象可在控制器和視圖中訪問。

這是聰明的部分。因為$ scope繼承的結構大致遵循DOM的結構,所以元素可以無縫地訪問它們自己的範圍,任何包含範圍,一直到全局$ scope(與全局範圍不同)。

這使得傳遞數據和在適當級別存儲數據變得更加容易。如果下拉列表展開,則只有下拉列表$ scope需要了解它。如果用戶更新其首選項,您可能希望更新全局$ scope,並且將自動提醒監聽用戶首選項的任何嵌套作用域。

這可能聽起來很複雜,事實上,一旦你放鬆它,就像飛行一樣。您不需要創建$ scope對象,AngularJS會根據您的模板層次結構正確且適當地為您實例化和配置它。然後,AngularJS使用依賴注入的魔力使其可用於您的組件(稍後將詳細介紹)。

手動DOM更改與數據綁定

在jQuery中,您可以手動完成所有DOM更改。您以編程方式構造新的DOM元素。如果您有一個JSON數組並且想要將它放到DOM中,則必須編寫一個函數來生成HTML並插入它。

在AngularJS中,您也可以這樣做,但我們鼓勵您使用數據綁定。更改您的模型,並且因為DOM通過模板綁定到它,您的DOM將自動更新,無需干預。

因為數據綁定是從模板完成的,所以使用屬性或大括號語法,這非常容易。與之相關的認知開銷很小,所以你會發現自己一直在做這件事。

<input ng-model="user.name" />

將input元素綁定到$scope.user.name。更新輸入將更新當前範圍中的值,反之亦然。

同樣:

<p>
  {{user.name}}
</p>

將在段落中輸出用戶名。它是一個實時綁定,因此如果$scope.user.name值更新,模板也會更新。

Ajax一直都是

在jQuery中進行Ajax調用相當簡單,但它仍然可以考慮三次。這需要考慮增加的複雜性,以及需要維護的大量腳本。

在AngularJS中,Ajax是您的默認首選解決方案,它一直在發生,幾乎沒有您注意到。您可以包含ng-include模板。您可以使用最簡單的自定義指令應用模板。您可以在服務中包裝Ajax調用,並創建一個GitHub服務或Flickr服務,您可以輕鬆訪問它。

服務對象與助手功能

在jQuery中,如果我們想完成一個小的非dom相關任務,比如從API中提取一個feed,我們可能會在我們的閉包中寫一個小函數來完成它。這是一個有效的解決方案,但如果我們想要經常訪問該Feed,該怎麼辦?如果我們想在另一個應用程序中重用該代碼怎麼辦?

AngularJS為我們提供服務對象。

服務是包含函數和數據的簡單對象。他們總是單身,這意味著他們永遠不會超過一個。假設我們想要訪問 API,我們可能會編寫一個Service定義這樣做的方法。

假設我們有購物車。我們可以定義一個ShoppingCartService來維護我們的購物車,並包含添加和刪除項目的方法。因為服務是單例,並且由所有其他組件共享,所以任何需要的對像都可以寫入購物車並從中提取數據。它始終是相同的購物車。

服務對像是自包含的AngularJS組件,我們可以根據需要使用和重用它們。它們是包含函數和數據的簡單JSON對象。它們總是單例,因此如果您將數據存儲在一個地方的服務中,您可以通過請求相同的服務將數據傳輸到其他地方。

依賴注入(DI)與Instatiation - 也稱為de-spaghettification

AngularJS為您管理您的依賴項。如果你想要一個對象,只需引用它,AngularJS就會為你得到它。

在你開始使用它之前,很難解釋這是多麼大的時間。在jQuery中沒有像AngularJS DI那樣的東西。

DI意味著您不是編寫應用程序並將它們連接在一起,而是定義一個組件庫,每個組件都由一個字符串標識。

假設我有一個名為'FlickrService'的組件,它定義了從Flickr中提取JSON提要的方法。現在,如果我想編寫一個可以訪問Flickr的控制器,我只需要在聲明控制器時按名稱引用'FlickrService'。AngularJS將負責實例化組件並使其可供我的控制器使用。

例如,我在這裡定義一個服務:

myApp.service('FlickrService', function() {
  return {
    getFeed: function() { // do something here }
  }
});

現在,當我想使用該服務時,我只是按名稱引用它:

myApp.controller('myController', ['FlickrService', function(FlickrService) {
  FlickrService.getFeed()
}]);

AngularJS將認識到需要一個FlickrService對象來實例化控制器,並為我們提供一個。

這使得連接在一起非常容易,並且幾乎消除了任何傾向於spagettification的趨勢。我們有一個平面的組件列表,當我們需要時,AngularJS將它們逐個交給我們。

模塊化服務架構

jQuery對如何組織代碼幾乎沒有說明。AngularJS有意見。

AngularJS為您提供了可以放置代碼的模塊。例如,如果您正在編寫與Flickr對話的腳本,則可能需要創建一個Flickr模塊來包裝所有與Flickr相關的函數。模塊可以包含其他模塊(DI)。您的主應用程序通常是一個模塊,這應該包括您的應用程序將依賴的所有其他模塊。

您可以獲得簡單的代碼重用,如果您想基於Flickr編寫另一個應用程序,您可以只包含Flickr模塊,您可以訪問新應用程序中的所有Flickr相關功能。

模塊包含AngularJS組件。當我們包含一個模塊時,該模塊中的所有組件都可以作為由其唯一字符串標識的簡單列表提供給我們。然後我們可以使用AngularJS的依賴注入機制將這些組件相互注入。

總結一下

AngularJS和jQuery不是敵人。可以非常好地在AngularJS中使用jQuery。如果您使用AngularJS以及(模板,數據綁定,$範圍,指令等),你會發現你需要很多比,否則你可能需要較少的jQuery。

要實現的主要是您的模板驅動您的應用程序。停止嘗試編寫可以完成所有操作的大插件。而是寫一些做一件事的指令,然後編寫一個簡單的模板將它們連接在一起。

少考慮不引人注目的JavaScript,而是考慮HTML擴展。

我的小書

我對AngularJS感到非常興奮,我寫了一本關於它的短篇小說,非常歡迎您在線閱讀http://nicholasjohnson.com/angular-book/。我希望它有用。


1.不要設計頁面,然後使用DOM操作進行更改

在jQuery中,您設計了一個頁面,然後將其設置為動態。 這是因為jQuery是為增強而設計的,並且從這個簡單的前提中獲得了令人難以置信的增長。

但是在AngularJS中,您必須從頭開始考慮您的架構。 而不是首先考慮“我有這塊DOM,我想讓它做X”,你必須從你想要完成的事情開始,然後去設計你的應用程序,然後最後去設計你的視圖。

2.不要使用AngularJS擴充jQuery

同樣,不要從jQuery做X,Y和Z的想法開始,所以我只是在模型和控制器的基礎上添加AngularJS。 當你剛剛開始時,這真的很誘人,這就是為什麼我總是建議新的AngularJS開發人員根本不使用jQuery,至少在他們習慣於“Angular Way”做事之前。

我在這里和郵件列表上看到很多開發人員使用150或200行代碼的jQuery插件創建這些精心設計的解決方案,然後他們將這些代碼粘合到AngularJS中,其中包含一系列令人困惑和錯綜複雜的回調和$apply ; 但他們最終讓它發揮作用! 問題在於,在大多數情況下,jQuery插件可以在AngularJS中以一小部分代碼重寫,突然間一切都變得易於理解和直接。

最重要的是:在解決問題時,首先要“在AngularJS中思考”; 如果你想不出解決方案,請問社區; 如果完全沒有簡單的解決方案, 那麼隨時可以找到jQuery。 但是不要讓jQuery成為拐杖或者你永遠不會掌握AngularJS。

3.始終從架構的角度思考

首先要知道單頁應用程序應用程序 。 他們不是網頁。 因此,我們需要像服務器端開發人員一樣思考,而不是像客戶端開發人員那樣思考。 我們必須考慮如何將我們的應用程序劃分為單獨的,可擴展的,可測試的組件。

那你怎麼做的呢? 你如何“在AngularJS中思考”? 以下是一些與jQuery形成對比的一般原則。

該觀點是“官方記錄”

在jQuery中,我們以編程方式更改視圖。 我們可以將下拉菜單定義為ul如下所示:

<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中,在我們的應用程序邏輯中,我們將使用以下內容激活它:

$('.main-menu').dropdownMenu();

當我們只看這個視圖時,並不是很明顯這裡有任何功能。 對於小型應用,這很好。 但對於非平凡的應用程序,事情很快就會變得混亂和難以維護。

但是,在AngularJS中,視圖是基於視圖的功能的官方記錄。 我們的ul聲明將是這樣的:

<ul class="main-menu" dropdown-menu>
    ...
</ul>

這兩個做同樣的事情,但在AngularJS版本中,任何看模板的人都知道應該發生什麼。 每當開發團隊的新成員加入時,她都可以查看這個,然後知道有一個名為dropdownMenu的指令在其上運行; 她不需要直截了當地回答正確的答案或篩選任何代碼。 該觀點告訴我們應該發生什麼。 更清潔。

AngularJS的新手開發人員經常會問一個問題:如何查找特定類型的所有鏈接並在其上添加指令。 當我們回复時,開發人員總是大吃一驚:你沒有。 但你不這樣做的原因是這就像是半jQuery,半AngularJS,並沒有好處。 這裡的問題是開發人員試圖在AngularJS的上下文中“執行jQuery”。 那永遠不會好起來的。 該觀點官方記錄。 在指令之外(以下更多內容),您永遠不會永遠不會更改DOM。 並且指令在視圖中應用,因此意圖很明確。

記住:不要設計,然後標記。 你必須設計,然後設計。

數據綁定

這是迄今為止AngularJS最強大的功能之一,並且我在上一節中提到了很多需要進行各種DOM操作。 AngularJS會自動更新您的視圖,所以您不必! 在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>

而現在我們使用的是Bootstrap警報框,而不是使用無序列表。 我們永遠不必更改控制器代碼! 但更重要的是,無論日誌在何處如何更新,視圖也會發生變化。 自動。 整齊!

雖然我沒有在這裡顯示,但數據綁定是雙向的。 因此,只需執行以下操作,即可在視圖中編輯這些日誌消息: <input ng-model="entry.msg" /> 。 有很多的欣喜。

不同的模型層

在jQuery中,DOM有點像模型。 但是在AngularJS中,我們有一個單獨的模型層,我們可以以任何方式管理,完全獨立於視圖。 這有助於上述數據綁定,保持關注點的分離 ,並引入更大的可測試性。 其他答案提到了這一點,所以我就把它留在那裡。

關注點分離

以上所有內容都與這個主題相關:將您的擔憂分開。 你的觀點作為應該發生的事情的官方記錄(大部分); 你的模型代表你的數據; 你有一個服務層來執行可重用的任務; 你做DOM操作並用指令擴充你的視圖; 然後將它們與控制器粘合在一起。 在其他答案中也提到了這一點,我將添加的唯一內容涉及可測試性,我將在下面的另一部分中討論。

依賴注入

為了幫助我們分離關注點, 依賴注入 (DI)。 如果你來自服務器端語言(從JavaPHP ),你可能已經熟悉了這個概念,但如果你是一個來自jQuery的客戶端人,那麼這個概念可能看起來從愚蠢到多餘到時髦。 但事實並非如此。 :-)

從廣義的角度來看,DI意味著您可以非常自由地聲明組件,然後從任何其他組件聲明組件,只需要詢問它的實例,它就會被授予。 您無需了解加載順序,文件位置或類似內容。 電源可能不會立即可見,但我只提供一個(常見)示例:測試。

讓我們說在我們的應用程序中,我們需要一個通過REST API實現服務器端存儲的服務,並且根據應用程序狀態,還需要本地存儲。 在我們的控制器上運行測試時,我們不希望與服務器通信 - 畢竟我們正在測試控制器 。 我們可以添加一個與原始組件同名的模擬服務,注入器將確保我們的控制器自動獲取假的 - 我們的控制器不會,也不需要知道差異。

說到測試......

4.測試驅動的開發 - 永遠

這實際上是關於體系結構的第3部分的一部分,但它非常重要,我將它作為自己的頂級部分。

在您看過,使用過或編寫的所有jQuery插件中,有多少有一個附帶的測試套件? 不是很多,因為jQuery不太適合。 但AngularJS是。

在jQuery中,唯一的測試方法通常是使用示例/演示頁面獨立創建組件,我們的測試可以對其執行DOM操作。 那麼我們必須單獨開發一個組件, 然後將其集成到我們的應用程序中。 多麼不方便! 很多時候,在使用jQuery開發時,我們選擇迭代而不是測試驅動開發。 誰可以怪我們?

但是因為我們有關注點分離,我們可以在AngularJS中迭代地進行測試驅動開發! 例如,假設我們想要一個超級簡單的指令在我們的菜單中指出我們當前的路線是什麼。 我們可以在應用程序視圖中聲明我們想要的內容:

<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();
}));

當我們運行測試時,我們可以確認它失敗了。 只有現在我們才能創建我們的指令:

.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' );
                }
            });
        }
    };
});

我們的測試現在通過我們的菜單按要求執行。 我們的開發既是迭代的, 也是測試驅動的。 妖獸爽。

從概念上講,指令不是打包的jQuery

您經常會聽到“只在指令中執行DOM操作”。 這是必要的。 善意對待它!

但是讓我們深入一點......

一些指令只是裝飾視圖中的內容(想想ngClass ),因此有時會直接進行DOM操作,然後基本完成。 但是如果指令就像一個“小部件”並且有一個模板,那麼它應該尊重關注點的分離。 也就是說,模板應該在很大程度上獨立於鏈接和控制器功能中的實現。

AngularJS附帶了一整套工具,可以輕鬆實現這一目標。 使用ngClass我們可以動態更新類; ngModel允許雙向數據綁定; ngShowngHide編程方式顯示或隱藏元素; 還有更多 - 包括我們自己寫的那些。 換句話說,我們可以在沒有 DOM操作的情況下做各種各樣的超棒。 DOM操作越少,測試指令就越容易,它們的樣式就越容易,將來它們就越容易改變,它們的可重用性和可分發性就越高。

我看到許多開發人員對AngularJS很新,使用指令作為拋出一堆jQuery的地方。 換句話說,他們認為“因為我不能在控制器中進行DOM操作,所以我會把代碼放在指令中”。 雖然這當然要好得多,但它通常仍然是錯誤的

想想我們在第3節中編寫的記錄器。即使我們把它放在一個指令中,我們仍然希望用“Angular Way”來做。 它仍然不需要任何DOM操作! 很多時候DOM操作是必要的,但它比你想像的少得多! 在應用程序中的任何位置進行DOM操作之前,請先問問自己是否真的需要。 可能有更好的方法。

這是一個快速示例,顯示了我最常見的模式。 我們想要一個可切換的按鈕。 (注意:這個例子有點人為,並且表示更複雜的情況,以完全相同的方式解決。)

.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才能工作,jqLit​​e( angular.element )將始終使用jQuery(如果已加載)! 所以我們不需要使用$ - 我們可以使用angular.element
  4. 第四,與第三個密切相關的是,jqLit​​e元素不需要包裝在$ - 傳遞給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;
            };
        }
    };
});

同樣,模板內容在模板中,因此您(或您的用戶)可以輕鬆地將其交換為滿足任何必要樣式的模板,並且不必觸及邏輯 。 可重用性 - 熱潮!

還有所有其他好處,比如測試 - 這很容易! 無論模板中有什麼內容,指令的內部API都不會被觸及,因此重構很容易。 您可以根據需要更改模板,而無需觸及指令。 無論你改變什麼,你的測試仍然通過。

w00t!

因此,如果指令不僅僅是類jQuery函數的集合,它們是什麼? 指令實際上是HTML的擴展 。 如果HTML不需要它做某事,你可以編寫一個指令來為你做,然後就像使用它一樣使用它。

換句話說,如果AngularJS沒有開箱即用,請考慮團隊如何完成它以適應ngClickngClass等。

摘要

甚至不使用jQuery。 甚至不包括它。 它會阻止你。 當你遇到一個問題,你認為你已經知道如何在jQuery中解決,在你達到$ ,試著考慮如何在AngularJS的範圍內做到這一點。 如果你不知道,請問! 20次中有19次,最好的方法是不需要jQuery並嘗試使用jQuery解決它,為您提供更多的工作。


AngularJS和jQuery:

除了JQLite功能之外,AngularJs和JQuery在每個級別都完全不同,一旦你開始學習AngularJs的核心功能,你就會看到它(我在下面解釋過)。

AngularJs是一個客戶端框架,用於構建獨立的客戶端應用程序。JQuery是一個圍繞DOM的客戶端庫。

AngularJs Cool Principle - 如果您希望在UI上進行一些更改,請從模型數據更改角度進行思考。更改您的數據和UI將重新呈現自己。你不需要每次都玩DOM,除非並且直到它幾乎不需要,並且也應該通過Angular Directives來處理。

要回答這個問題,我想與AngularJS分享我在第一個企業應用程序上的經驗。這些是Angular提供的最強大的功能,我們開始改變我們的jQuery思維模式,我們將Angular看作框架而不是庫。

雙向數據綁定是驚人的:我有一個網格,所有功能都是UPDATE,DELTE,INSERT。我有一個數據對象,使用ng-repeat綁定網格模型。您只需編寫一行簡單的JavaScript代碼即可進行刪除和插入,就是這樣。當網格模型立即更改時,網格會自動更新。更新功能是實時的,沒有代碼。你覺得很棒!

可重複使用的指令是超級的:在一個地方寫指令並在整個應用程序中使用它。我的天啊!!! 我使用這些指令進行分頁,正則表達式,驗證等等。真的很酷!

路由很強:由您的實現決定如何使用它,但它需要很少的代碼行來路由請求以指定HTML和控制器(JavaScript)

控制器很棒:控制器會處理自己的HTML,但這種分離對於常見功能也很有效。如果要在主HTML上單擊按鈕調用相同的函數,只需在每個控制器中寫入相同的函數名稱並編寫單獨的代碼。

插件:還有許多其他類似功能,例如在您的應用中顯示疊加層。您不需要為它編寫代碼,只需使用可用作wc-overlay的覆蓋插件,這將自動處理所有XMLHttpRequest(XHR)請求。

RESTful架構的理想選擇:作為一個完整的框架,AngularJS非常適合使用RESTful架構。調用REST CRUD API非常簡單

服務:使用服務編寫公共代碼,在控制器中編寫較少代碼。服務可用於共享控制器之間的共同功能。

可擴展性:Angular使用angular指令擴展了HTML指令。在html中編寫表達式並在運行時評估它們。創建自己的指令和服務,並在不需要額外努力的情況下在另一個項目中使用它們。


jQuery是一個DOM操作庫。

AngularJS是一個MV *框架。

事實上,AngularJS是為數不多的JavaScript MV *框架之一(許多JavaScript MVC工具仍屬於類別庫)。

作為一個框架,它託管您的代碼,並擁有決定調用什麼以及何時調用的所有權!

AngularJS本身包含一個jQuery-lite版本。因此,對於一些基本的DOM選擇/操作,您實際上不必包含jQuery庫(它可以節省許多字節以在網絡上運行。)

AngularJS具有用於DOM操作和設計可重用UI組件的“指令”概念,因此您應該在需要執行與DOM操作相關的東西時使用它(指令只是在使用AngularJS時應該編寫jQuery代碼的地方)。

AngularJS涉及一些學習曲線(超過jQuery :-)。

- >對於任何來自jQuery背景的開發人員,我的第一個建議是“在開始使用像AngularJS這樣的豐富框架之前,將JavaScript作為一流語言學習!” 我用艱難的方式了解了上述事實。

祝好運。


jQuery:你對DOM元素的“查詢DOM ”以及做某事有很多想法。

AngularJS:模型是事實,你總是從那個角度思考。

例如,當您從要在DOM中以某種格式顯示的服務器獲取數據時,在jQuery中,您需要'1。找到'你要在DOM中放置這些數據的位置,'2。通過創建新節點或僅設置其innerHTML更新/附加它。然後,當您想要更新此視圖時,您將'3。找到'位置'和'4。UPDATE“。在AngularJS中,在從服務器獲取和格式化數據的相同上下文中完成所有查找和更新循環。

使用AngularJS,您可以獲得模型(已經習慣的JavaScript對象),模型的值會告訴您模型(顯然)和視圖,模型上的操作會自動傳播到視圖,所以你不要我必須考慮一下。你會發現自己在AngularJS中不再在DOM中找到東西。

要以另一種方式,在jQuery中,你需要考慮的CSS選擇器,那就是,哪裡是divtd具有類或屬性,等等,讓我能得到他們的HTML或顏色或價值,但在AngularJS,你會發現自己這樣想:我在處理什麼模型,我會將模型的值設置為true。您不必擔心反映此值的視圖是複選框還是駐留在td元素中(您在jQuery中經常需要考慮的細節)。

在AngularJS中使用DOM操作,您會發現自己添加了指令和過濾器,您可以將其視為有效的HTML擴展。

你將在AngularJS中體驗到的另一件事:在jQuery中你調用jQuery函數很多,在AngularJS中,AngularJS會調用你的函數,所以AngularJS會“告訴你如何做事”,但是它的好處是值得的,所以學習AngularJS通常意味著學習AngularJS想要的東西或者AngularJS要求你展示你的功能的方式,它會相應地調用它。這是使AngularJS成為框架而不是庫的因素之一。


他們是蘋果和橘子。你不想比較它們。他們是兩件不同的事。AngularJs已經內置了jQuery lite,它允許你執行基本的DOM操作,甚至不包括完整的jQuery版本。

jQuery是關於DOM操作的。它解決了所有跨瀏覽器的痛苦,否則你將不得不處理,但它不是一個允許你將你的應用程序劃分為AngularJS等組件的框架。

AngularJs的一個好處是它允許您在指令中分離/隔離DOM操作。有內置指令可供您使用,例如ng-click。您可以創建自己的自定義指令,其中包含所有視圖邏輯或DOM操作,因此您最終不會將DOM操作代碼混合在應該處理業務邏輯的控制器或服務中。

Angular將您的應用分解為 - 控制器 - 服務 - 視圖 - 等

還有一件事,就是指令。它是一個可以附加到任何DOM元素的屬性,你可以在其中使用jQuery,而不必擔心你的jQuery會與AngularJs組件發生衝突或者與它的架構混淆。

我從參加過的聚會中聽到,Angular的一位創始人表示他們非常努力地將DOM操作分開,所以不要試圖將它們包括在內。





angularjs