背景
作為一個全棧工程師,前端 JS 庫的使用是必備的技能。除了老牌的 jQuery,當下還有 React/Angular/Vue 這三座大山,但是我已經使用過 Angular 1 和 2,而且 Angular 作為 Google 的重要產品應該能長期開發維護。因此我選擇了 Angular 2 作為前端的主力 JS 庫。
Angular 2 是什么
以下為 Wiki 上的定義:
AngularJS 是一個完整的基于 JavaScript 的開源的前端網絡應用框架,主要由 Google 和一個個人和組織組成的社會維護,用以處理在開發單頁面應用中遇到的多個挑戰。這個 JavaScript 組件補充了 Apache Cordova,這個跨國那就愛用于開發跨平臺移動應用。它通過提供一個針對于客戶端側 MVC 和 MVVM 結構 ,和在豐富的網絡應用中常用的組件配合,致力于簡化開發和測試。AngularJS 框架通過首選讀取 HTML 頁面工作,該頁面已經嵌入了附加的定制化的標簽屬性。Angular 將這些屬性翻譯成指令來將頁面的輸入或者輸出部分綁定到一個被標準 JavaScript 變量代表的模型上。這些 JavaScript 變量的值可以在代碼中被手動設置,或者從靜態的或動態的 JSON 資源中獲取。AngularJS 基于聲明式編程應該用來創建用戶界面和連接軟件組件,同時命令時編程更適合定義一個應用的業務邏輯的理念被構建。該框架通過允許模型和視圖自動同步的雙向綁定,改編并擴展了傳統的 HTML 來體現動態內容。作為結果,AngularJS 由于提升可測試性和性能的目標,不再強調 DOM 的操作。
AngularJS 的設計目標包括:
- 從應用邏輯中解耦 DOM 操作。通過這種方式組織代碼,高耦合所產生的困難被明顯影響;
- 從服務器側解耦應用的服務器側。該措施將允許并行工作,并允許雙方的復用;
- 針對構造一個應用的過程提供一個結構:從設計 UI,到寫業務邏輯,再到測試;
Angular 的出現以及解決了哪些問題
Angular 出現之前
JavaScript 是一門獨立的語言,可以通過瀏覽器訪問 DOM,通過控制被渲染成的 DOM 樹,增強網頁的表現力。
再來看 jQuery,以下為 Wiki 上的定義:
jQuery,說到底,是一個 DOM 操作庫。DOM 是一個網頁里所有元素樹形結構表現,并且 jQuery 簡化了查找、選擇和操作這些 DOM 元素的語法。jQuery 也提供了一個事件處理的范式,超越了基本的 DOM 元素的選擇和操作。在代碼中的同一個地方的同一個步驟,事件賦值和事件回調函數定義就被完成了。jQuery 也力求包含其他常用的 JavaScript 功能。
總結起來,jQuery 其實就是 JavaScript 的高級封裝,將常用的功能封裝成高層的函數,用起來比較方面。jQuery 是庫,而不是框架。相比原生的 JavaScript,jQuery的優點是用較少的代碼就可以實現相同的功能,并能夠更好的處理事件。但是其缺點也很明顯,包括在處理頁面數據的變化和一致性上需要花費大量的時間和精力,并且沒有固定的開發范式,不能很好的約束開發規范和設計模式,導致代碼質量參差不齊。
Angular 和 jQuery 的區別
- jQuery 是庫,而 Angular 是框架。庫是工具的集合,框架是開發規范;
- 思維方式。這也是我剛開始學習 Angular 感受到的最大的不同。jQuery 是很直觀的思維,想修改頁面上的哪里,通過 DOM 直接修改就可以。而 Angular 作為框架,則提供的固定的 MVVM 設計模式,把視圖層的數據和控制器層的數據統一了起來,將數據抽象成了一個對象而不僅僅是頁面上的文本;
- UI 和業務邏輯的耦合性;
Angular 2 和 Angular 1 的區別
Angular 1 的遺留問題
雖然 Angular 1 很優秀,還是有很多問題和缺點:
- MVVM 化還不夠徹底。還保留有很多中間的
- 對于移動應用不夠友好;
- 需要學習很多 Angular 1 的定制化標簽;
- 路由功能太薄弱;
- 弱類型。當然,這個其實是 JavaScript 的問題;
Angular 2 的改變
Angular 2 的區別
- 面向移動應用和性能優化;
- 更多語言選擇。通過 TypeScript 可以有效增強類型檢查等功能;
- 組件化;
- 直接使用有效的 HTML DOM 屬性和事件;
- 可以自主選擇單向還是雙向綁定;
- 路由語法;
- 綁定方式;
Angular 2 的特性
- 跨平臺
- 給予 app 式的網頁體驗;
- 借助其他技術,構建原生移動應用;
- 結合原生操作系統的 API,創建跨平臺桌面應用;
- 速度和性能
- 利用模板開發,最終產品再進行高度優化;
- 支持眾多后臺服務,服務端渲染首屏快速打開,SEO 優化友好;
- 用戶可單獨加載需要的代碼;
- 生產率
- 模板語法快速構建;
- 命令行工具提升效率;
- IDE 友好;
- 完整開發過程
- 單元測試和場景測試相結合;
- 通過 API 創建動畫;
- 高度的可訪問性,方便各類人群;
Angular 2 常用依賴
- core-js。是針對 JavaScript 的模塊標準庫。包括 ECMAScript5/6/7 的一些“墊片”。意思是允許原本那些不支持 ECMAScript 特性的瀏覽器支持這些特性。
- rxjs。RxJS 是可觀察流的異步編程 API 的 JavaScript 實現,是一種設計模式的語言實現。之前我已經在 HTTP 的請求中已經大量運用了,不過當時只是簡單的語法使用,沒有看到其全貌;
- zone。zone 是一個可以在異步任務之間進行持久性傳遞的執行過程上下文。你可以把它想象成針對 JavaScript 虛擬機的線程本地存儲。這里暫時不再繼續討論,詳情可以看[此文章][zone];
- reflect-metadata。也是墊片。用來加入 ECMAScript 7 的裝飾器功能,并提供一個 ECMAScript 7 對裝飾器元數據 的反射 API。也是 Angular 2 種的基礎功能,務必要提前了解一下。[zone]: http://blog.thoughtram.io/angular/2016/01/22/understanding-zones.html
全面掌握 Angular 2 的方向
- 理解依賴注入模式;
- 理解單/雙向綁定;
- 理解裝飾器模式;
- 理解觀察者模式;
Angular 2 的高效工具
- Angular-CLI;
- Augury;
- Codelyzer;
- Angular-seed;
詳細的區別可以查閱此文章。還可以通過這個 ng-conf 大會上的視頻更直觀地發現 Angular 2 和 1 的區別以及當前的特性。
Angular 2 啟動原理
Angular 2 在瀏覽器中如何引導
TODO:在此寫下瀏覽器如何引導 Angular 的流程。
Angular 2 開發
基礎開發流程
- 建立基礎配置文件,例如 package.json/tsconfig.json,以及模塊加載配置文件(可以采用 SystemJS 或者 Webpack );
- 建立根模塊。模塊是 Angular 2 RC 5 以后引入的新概念,我理解類似于 Node.js 的 npm 包管理,即把某些功能封裝在獨立的模塊中,便于管理、方便解耦;
- 建立根組件并引入到根模塊中。組件是 Angular 應用的基本構造塊。每個組件都會通過與它相關的模板來控制屏幕上的一小塊(視圖)。根模塊只是一個功能集合包,但根模塊文件本身不包含任何功能,因此需要需要至少有一個根組件來提供功能。根組件表示出應用的主視圖,它是所有其他視圖的宿主;
- 建立 Angular 引導文件 main.ts。用于在瀏覽器中引導根模塊;
- 定義宿主頁面 index.html;
- 編譯并運行應用;為什么分離模塊、組件和引導文件:應用的引導過程和模塊或者視圖展現是相互獨立的關注點。分離以后方便解耦和測試,也可以以后更換引導器。
問題
閱讀官方教程中出現的問題
問題
- 開發指南 -> 架構:父組件和子組件如何做數據綁定;
-
開發指南 -> 架構:依賴注入的提供商到底是什么,和注入的依賴是什么關系。我現在的感覺是,提供商的類本身,注入的依賴是類的實例; - 開發指南 -> 用戶輸入:
(click)="onClick()"
,這個 click 事件在 DOM 中和綁定的 button 元素是什么關系; - 開發指南 -> 表單:
moduleId = module.id
是什么意思; -
開發指南 -> 表單:雙向綁定的過程中,是什么機制使得變量能在 DOM 和組件之間來回傳遞,而不需要監聽 keyup 等事件; - 開發指南 -> 表單:組件里面的
get diagnostic()
是什么意思。是 JavaScript 的 getter 和 setter 么。這又是什么意思; - 開發指南 -> 表單:forms.css 里的
.ng-invalid:not(form)
是什么意思; - 開發指南 -> 表單:
#name="ngModel"
這句作何解釋,看了下面的解釋還是不清楚,這樣賦值了以后,name 是否就表示了一個表單控件呢。還有#heroForm="ngForm"
也不理解; - 開發指南 -> 依賴注入:非類依賴的那部分不是很理解,尤其是
OpaqueToken
的使用; - 開發指南 -> 模板語法:插值表達式 Interpolation 和模板表達式 Template expression 有什么區別。是不是插值表示兩個花括號和里面的模板表達式這個整體呢;
-
開發指南 -> 模板語法:;[routerLink]="['/']"
這種的綁定目標到底是元素、組件還是指令的屬性啊,覺得都不是 - 開發指南 -> 模板語法:使用 EventEmitter 實現自定義事件的具體應用場景是什么?具體如何使用;
- 開發指南 -> 風格指南:特性區的模塊該如何定義,特性區的模塊文件和路由模塊文件是什么關系;
- 開發指南 -> 風格指南:風格 04-10,把可能被應用到其他特性模塊使用的公共資產(如組件、指令和管道)放在 SharedModule 中,這些資產傾向于共享自己的新實例(而不是單例)。這個共享新實例和單例分別是什么意思;
- 開發指南 -> 風格指南:風格 04-11,
CoreModule
到底是什么,應該怎么使用; - 教程 -> HTTP:InMemoryDataService 中到底如何設置可以模擬數據服務中的 url 并匹配;
- 高級文檔 -> 路由與導航:index.html 中設置的
<base href="/">
為什么將 app 作為根目錄,index.html 和 app 目錄不是平級的嗎,根目錄應該是 src 啊;18. 高級文檔 -> HTTP 客戶端:為什么 Angular 官方鼓勵服務器發送數據的時候將真實數據放在 data 屬性下面; - angular2-jwt:有個叫做 JwtHelper 的類,為什么不能作為供應商;
- 如何避免 angular2 本身的 selector 導致 html 原有的結構發生改變,從而影響 SEO 和 CSS 規則;
- 如何
解答
- 依賴注入的提供商可以是很多種形態,可以是類或者是值,被注入的依賴是提供商可以轉換成的實例對象;
- 在開發指南 -> 表單中就有 ngModel 的雙向綁定原理的解釋。但是還需要深入了解屬性指令是怎么回事,為什么 ngModel 指令能夠影響表單的值;
- 綁定目標是指令屬性;
最佳實踐
- 不要在 SharedModule 中為惰性加載模塊提供服務,將服務放在 CoreModule 中全局使用;