給Java程序員的Angular快速指南

太長不讀版:

Spring + Angular 的全棧式開發(fā)垛吗,生產(chǎn)力高、入門難度低(此處省略一萬字)叠艳,是 Java 程序員擴展技術棧的上佳選擇听怕。

如果你動心了,接下來就是那省略的一萬字……

痛點 - 團隊分工與協(xié)作

在前后端分離的開發(fā)方式中虑绵,拆故事卡是個難題尿瞭。

如果前后端同時工作于一張卡上,但配合不夠默契或節(jié)奏不同步翅睛,就會出現(xiàn)一方空轉的現(xiàn)象声搁。如果前后端各一張卡,又不容易實現(xiàn)端到端驗收捕发,可能導致先做完的一方在另一個結束后還要再次返工的現(xiàn)象疏旨。而且,兩個人都要深入理解這張卡所描述的業(yè)務細節(jié)扎酷,而這往往是不必要的檐涝。

更重要的是,BUG 最容易出現(xiàn)在邊界處法挨。

業(yè)務卡不像技術卡那樣能跟其它卡片劃出明確的邊界谁榜,前后端之間必然具有千絲萬縷的聯(lián)系。這種聯(lián)系越緊密凡纳,出 BUG 的機會也就越大窃植。

技術架構上的挑戰(zhàn),也會反映到人員架構上荐糜。我們?nèi)祟惒皇切庆`巷怜,無法做到心靈相通。因此前后端開發(fā)者需要對合作方所擁有的知識進行很多主觀假設暴氏。

如果這些假設中存在錯誤延塑,又沒能及時溝通來消除它(甚至可能都意識不到這些假設的存在),那么 BUGs 就要登場了答渔。而像業(yè)務卡這種級別的密切協(xié)作中可能隱含的假設實在太多了关带,除非經(jīng)過長時間的磨合,否則很難消除研儒,但大多數(shù)項目上可沒有那么多磨合時間豫缨。

解決方案 —— 全棧式開發(fā)

人員架構

該如何解決呢?克服上述問題的辦法就是全棧式開發(fā)端朵。也就是說好芭,調整人員架構去適應技術架構。

簡單來說:每個人都同時寫前端和后端冲呢。他不必是前端專家也不必是后端專家舍败,但是兩邊都要會寫。他的關注點不是技術知識敬拓,而是業(yè)務知識邻薯。他的工作目標是貫穿前后端的價值流,對單個故事進行端到端交付乘凸。

但是厕诡,要如何克服實現(xiàn)中遇到的技術難題以及保障代碼質量呢?那就要靠團隊中的技術專家了营勤。

總體來說灵嫌,全棧式團隊的人員架構就是大量全棧業(yè)務工程師 + 少量技術專家。當然葛作,技術專家不一定要安排單獨的人擔任寿羞,只要技術滿足要求,也可以由某位全棧工程師兼任赂蠢,只是他做計劃時要留出做技術支持的時間堕汞。

通過 Code Review债查、Pair 等敏捷實踐,技術專家可以起到團隊放大器的作用,讓整個團隊的生產(chǎn)力翻倍奈泪。

個人工作流

作為全棧工程師,你首先要對一個業(yè)務故事進行建模活孩,包括業(yè)務模型柿赊、視圖模型、領域模型绍傲、存儲模型等扔傅,建模的過程也就是你理解業(yè)務的過程。這時候要注意多和 BA烫饼、UX猎塞、DBA 等溝通,以確保你的理解不存在方向性錯誤杠纵,不要太沉迷細節(jié)荠耽,防止見木不見林。

單源建模的優(yōu)點是這些模型之間很容易保持一致比藻,這無論是對前期開發(fā)還是對后期維護都是有幫助的铝量。

建模完畢之后倘屹,就要開始設計前后端之間的接口了。接口是前后端分離式架構中最容易開裂的地方慢叨,也是對未來的演化影響最大的地方之一纽匙。它很重要,但也不必小心翼翼的 —— 全棧工程師對接口變化的適應能力要強大得多拍谐。因為接口的提供方和消費方都是你烛缔,信息非常透明,不存在任何額外的假設轩拨。對不完美的接口践瓷,你可以在后續(xù)開發(fā)過程中迭代好幾個版本來把它打磨到最理想的形態(tài),改接口將不再沉重和危險亡蓉。

接口設計完之后晕翠,有兩種路徑,取決于界面和后臺邏輯的特點砍濒。

如果對業(yè)務理解還不是很有信心崖面,那就先用 Mock 的方式把前端寫出來,然后把這個 Mock 版當做可執(zhí)行的原型去跟 BA梯影、QA巫员,甚至客戶進行實際操作演示,用可操作原型來驗證你對業(yè)務的理解甲棍。對一般粒度的故事卡简识,線框圖級的可操作原型通常能在半天內(nèi)完成。通過原型盡早發(fā)現(xiàn)錯誤感猛,可以避免以后沉重的返工七扰。而且,這是一個可演化原型陪白,不是一次性原型颈走,不會浪費掉。

如果后端很容易實現(xiàn)(但先不必做優(yōu)化工作)咱士,那么就可以不必 Mock立由,先初步完成后端開發(fā),并讓前端直接對接真實的后端序厉。先拿這個比 Mock 版原型更逼真一點的原型串起流程锐膜,然后再進行優(yōu)化和打磨工作。

在整個過程中弛房,你可以根據(jù)不同的需要道盏,來與不同的技術專家進行 Pair,并且你最終的代碼也會在例行 Code Review 中得到前端專家、后端專家荷逞、DBA媒咳、DevOps 專家等人的點評和改進,不必擔心自己在單項技術上的短板影響交付种远。

全棧的挑戰(zhàn)

全棧固然美好涩澡,但也要迎接很多挑戰(zhàn),而 Angular 會幫你分擔這些痛苦院促。

首先遇到的挑戰(zhàn)是語言切換

前后端 JavaScript 全棧固然在特定場景下有效,但是在很多企業(yè)應用中是遠遠不夠的斧抱。至少到目前為止常拓,企業(yè)應用還主要是 Java 的天下。本文所討論的也都是 Java + JavaScript 的全棧辉浦。

我們都知道弄抬,Java 和 JavaScript 之間的差異就像雷鋒和雷峰塔之間的差異。Java 程序員通常很難適應 JavaScript宪郊,不過現(xiàn)在有了更像 Java 的 TypeScript掂恕。而 Angular 就是原生基于 TypeScript 的框架,稍后我會做一個摘要講解弛槐,你會發(fā)現(xiàn)自己很熟悉它的味道懊亡。

(圖片來自:http://t.cn/RobG5nA

其次是基礎設施

基于 JRE 的構建體系和基于 NodeJS 的構建體系看似差異很大,實際上卻有很大程度的相似性乎串。但前端兩年一換代的瘋狂迭代店枣,以及層出不窮的新名詞、新工具叹誉,仍然難免會讓后端心生恐懼鸯两。不過不用擔心,Angular 替你封裝了一切长豁,你只需要裝上 NodeJS 環(huán)境和 Angular CLI 就可以了钧唐。你不需要關心它封裝了哪些第三方工具,至于今后的工具鏈怎么瘋狂迭代匠襟,那都是 Angular 開發(fā)組需要操心的事钝侠。

最后是最佳實踐

前后端從表面上看差異很大 —— 前端輕靈,后端穩(wěn)重酸舍。

但在我看來它們很少存在本質性的差異机错,更像是不同的社區(qū)文化導致的結果。而在更高的層次上看父腕,兩邊的技術具有很大的相似性弱匪。無論是函數(shù)式編程還是工程化開發(fā),都不是某一方所特有的,而是 IT 領域的共同資產(chǎn)萧诫。況且斥难,它們還一直在相互影響,相互滲透 —— 這兩年后端變得越來越輕靈帘饶,而前端變得越來越工程化哑诊。長遠來看,文化合流是必然的趨勢及刻。

事實上镀裤,前后端很多優(yōu)秀設計和最佳實踐都是殊途同歸的。像 Spring 和 Angular缴饭,它們都采用了久經(jīng)考驗的面向對象范式暑劝;都使用依賴注入技術進行解耦;都擁抱函數(shù)式編程颗搂;都提供了豐富的 AOP 支持等担猛。雖然細節(jié)上各有千秋,但僅從代碼上就能感受到它們之間的相似性丢氢。

我該怎么辦傅联?

聽完這些,你是否已經(jīng)蠢蠢欲動疚察?接下來蒸走,就跟我開始 Angular 之旅吧。

語言 - TypeScript

Angular 使用 TypeScript 作為主要開發(fā)語言貌嫡。如果你還不熟悉 TypeScript载碌,那可以把它看做 Java 和 JavaScript 的混合體。TypeScript 是 ES6 的超集衅枫,這就意味著嫁艇,任何有效的 ES6 語法都同樣是有效的 TypeScript 語法。

事實上弦撩,從 Java 出發(fā)學 TypeScript步咪,可能比從 ES5/6 學 TypeScript 還要簡單一些。不過益楼,對于 Javaer 來說猾漫,學習 TypeScript 時有一些重要的不同點要特別注意。

TypeScript 的類型只存在于編譯期

TypeScript 的一個首要設計約束就是要兼容 ES5/6感凤,因此不能隨意增加基礎設施悯周,而像 Java 這種級別的類型支持在原生 JavaScript 中是根本不存在的。

你可以把 TypeScript 的類型看做僅僅給編譯器和 IDE 用的陪竿。因此禽翼,在運行期間沒有任何額外的類型信息(只有 ES5 固有的那一小部分),像 Java 那樣完善的反射機制是很難實現(xiàn)的(可以用裝飾器/注解實現(xiàn),但比較繁瑣)闰挡。

TypeScript 的裝飾器 vs. Java 的注解

TypeScript 的裝飾器和 Java 的注解在語法上很相似锐墙,但其實在語法含義上有著本質的區(qū)別。TypeScript 的裝飾器是個函數(shù)长酗,而 Java 的注解是個數(shù)據(jù)溪北。語法上,裝飾器名字后面必須帶括號夺脾,不能像注解那樣省略之拨。

不過,在 Angular 中咧叭,TypeScript 裝飾器的實際用途就是為類或屬性添加注解而已蚀乔。因此,有些文章中佳簸,包括早期的官方文檔中乙墙,用的都是注解的說法颖变。當然生均,以后寫新文章還是都用裝飾器吧。

類與接口

TypeScript 中的類和 ES6 中的類幾乎是一樣的腥刹,和 Java 中的類也很相似马胧。

接口則不同,我們前面說過衔峰,TypeScript 中的類型信息只存在于編譯期佩脊,而接口作為“純粹的”類型信息,也同樣只存在于編譯期垫卤。也就是說威彰,在運行期間你無法判斷某個對象的類是否實現(xiàn)了某個接口。在 Angular 中穴肘,實際上使用的是暴力探測法來判斷的:查找這個接口中規(guī)定的方法(只匹配名稱)歇盼,如果存在,則認為實現(xiàn)了這個接口评抚。

這也意味著豹缀,你就算不顯式 implements 接口,但只要聲明了其中的方法慨代,Angular 也會正確的識別它邢笙。但這不是一個好習慣,你應該始終顯式 implements 接口侍匙,刪除時也要同時刪除接口聲明和對應的方法氮惯。不過也不用擔心,Angular 自帶的 lint 工具會幫你檢查是否有忘了顯式 implements 接口,多注意提示就可以了筐骇。

接口是給編譯器和 IDE 看的债鸡,這很有用。比如铛纬,我們可以在 IntelliJ/WebStorm 中聲明某個類實現(xiàn)了一個接口厌均,然后在這個類名上按 alt-enter ,就會出現(xiàn) “Implement interface XXX” 菜單 —— 就像 Java 中一樣告唆。事實上棺弊,一些 IDE 對 TypeScript 的支持程度已經(jīng)接近 Java 了:代碼提示、重構擒悬、類型檢查模她、簡短寫法提醒等,應有盡有懂牧。

值得注意的是:你也可以 implement 一個類侈净,而不僅是 extends 它,也就是說類可以在很多場景下代替接口僧凤!Angular 風格指南提出畜侦,“考慮在服務和可聲明對象(組件、指令和管道)中用類代替接口”躯保。因為運行期間接口不存在旋膳,所以在 Angular 中不能把接口用作依賴注入的 Token,也就不能像 Java 中那樣要求注入一個接口途事,并期待框架幫你找出實現(xiàn)了這個接口的可注入對象验懊,但類存在,因此尸变,上述場景下要盡量用抽象類來代替接口义图。

鴨子類型

為了支持 JavaScript 的動態(tài)性和遺留代碼,TypeScript 的類型匹配要比 Java 寬松不少召烂。比如碱工,如果兩個類(或接口)的屬性和方法(名稱、類型)都完全一致骑晶,那么即使它們沒有繼承關系痛垛,也可以相互替代(但如果類有私有屬性,則不能桶蛔,就算兩者完全一樣也不行)匙头。表面上看這可能過于寬松了,但在實際開發(fā)中還是很有用的仔雷,使用中要注意突破 Java 固有思維的限制蹂析。

在 TypeScript 中還支持可選屬性(name?: Type)舔示,也就是說如果兩個類的差別僅僅在可選屬性上,那么它們也是可以相互替代的电抚。

字面量與匿名類型

TypeScript 在某些方面可能更符合你對 Java “應該是什么樣子”的期待惕稻,至少在我看來是這樣。要聲明一個匿名對象蝙叛、匿名數(shù)組型變量俺祠?直接寫出來就好了const user = {name: 'tom', age: 20}。除此之外借帘,它還能聲明匿名類型 let user: {name: string, age: number} = ...蜘渣。

當然,也不能濫用它們肺然。對于一次性使用或暫時一次性使用的變量或類型蔫缸,用字面量和匿名類型很方便,可讀性也好际起,但是如果它要使用兩次以上拾碌,那就該重構成正式的類型了。

any

TypeScript 中的 any 大致相當于 Java 中的 Object街望,如果你看到通篇 Object 的 Java 代碼你會不會想罵街校翔?any 也一樣。不必完全禁止 any它匕,但如果你要使用 any展融,請務必先想清楚自己要做什么窖认。

void

如果你在 Java 中經(jīng)常使用 void豫柬,那就遵循同樣的原則用在 TypeScript 中。在 TypeScript 中扑浸,當你不聲明函數(shù)的返回類型時烧给,它會返回自動推斷的類型(沒有明確的 return value 語句時會推斷為 undefined 類型),如果你不想返回任何值喝噪,那么請把返回類型指定為 void 來防止別人誤用础嫡。

this

JavaScript 中的 this 是個奇葩。雖然這是函數(shù)式語言中的標配酝惧,但從語言設計上真是讓人忍不住吐槽榴鼎。要是能像 Groovy 那樣分出 this / owner / delegate 就好了。

吐槽歸吐槽晚唇,對于 Java 程序員巫财,該怎么避免自己踩坑呢?很簡單:對普通函數(shù)哩陕,任何涉及到 this 的地方都用箭頭函數(shù) ()=>平项,而不要用普通的 function foo()赫舒,因為前者是替你綁定好了符合直覺的 this 的;對方法闽瓢,不要把任何涉及到 this 的方法當作函數(shù)指針傳給別人接癌,但可以在模板中自由使用。在 Angular 中扣讼,這兩條原則可以幫你回避掉絕大部分 this 錯誤缺猛。更多的細節(jié)可以先不管,隨著使用經(jīng)驗的增加椭符,你會逐漸弄明白這些規(guī)則的枯夜。

其它

以上這些是開發(fā)中常遇到的注意事項,其它的特性我就不一一列舉了艰山,請自行參考 TypeScript 的官方文檔湖雹。

范式與模型

MVVM

Angular 的基本編程模型是 MVVM,你可以把它看做 MVC 的一個變種曙搬。事實上摔吏,這是一個很符合直覺的模型:你看到一個頁面,先在大腦中抽取出它的信息架構(屬性)和操作(方法)纵装,定義好它們之間的邏輯關系和處理流程征讲,這就是視圖模型(VM)。你把它們落實到代碼橡娄,變成內(nèi)存對象诗箍,然后 Angular 就會幫你把它和頁面(View)關聯(lián)起來。你不懂怎么操作 DOM挽唉?沒關系滤祖,你只要會操作內(nèi)存對象就可以了,這應該是你非常擅長的吧瓶籽?剩下的那些臟活兒 Angular 都會幫你搞定匠童。

不過,Angular 關心的只是“要有” VM塑顺,至于你如何生成這個 VM汤求,它并不會做任何假設和限制。

自由混搭與切換

你想怎么生成 VM严拒?

  • 像后端控制器那樣直接寫在組件中扬绪?沒問題!
  • 像后端那樣委托給服務裤唠?沒問題挤牛!
  • 像 Redux 那樣委托給單一 Store?沒問題巧骚!
  • 像 Java 8 Stream 那樣用流水線生成赊颠?沒問題格二!
  • 自己幾乎不處理,完全委托給后端 API竣蹦?沒問題顶猜!

這么多方式各有不同的適用場景,但也不必過早擔心如何選型痘括。只要你的組件設計合理(職責分明长窄、接口明確等),那么在這些方式之間切換纲菌,或者混用它們挠日,都不會很難。

作為起點翰舌,可以先直接寫在組件中嚣潜,然后按需重構成服務,服務中可以直接寫代碼椅贱,也可以實現(xiàn) Redux 風格的單一 Store懂算,或者用 RxJS 寫流水線。

RxJS

在 Angular 開發(fā)人員的成長過程中庇麦,有一個很重要的坎就是 RxJS计技,它的背后是 FRP(函數(shù)響應式編程)范式。不過對于 Javaer 來說山橄,它的門檻并不高垮媒。如果你會用 RxJava / RxGroovy 等 ReactiveX 族的任何一個庫,那么你幾乎可以不用專門再學航棱,它們都是同一個大家族睡雇,編程范式甚至部分操作符的名稱都一樣,稍微對比一下差異就可以了丧诺。如果不會入桂,請繼續(xù)往下讀(以下的討論也適用于 RxJava 等奄薇,不過我文中只用 RxJS 舉例)驳阎。

RxJS 是一種 FRP(函數(shù)響應式編程)庫,它同時具有函數(shù)式編程和響應式編程的優(yōu)點馁蒂。

如果你會用 Java 8 Stream呵晚,那么也有很多知識可以復用到這里。相對于 Java 8 Stream沫屡,RxJS 的限制稍微寬松一些饵隙,但我建議你仍然按照 Java 那種嚴格的方式使用它(比如不要對流外的變量賦值)。

所謂響應式編程沮脖,我們可以把它想象成一條流水線金矛,流水線上不斷傳送待加工的材料(原料芯急、半成品、成品等)驶俊,流水線上每個工序的工人負責對傳送到眼前的材料進行一定的處理(做出響應)娶耍,然后放回流水線,接著它就會被傳送到下一個工序饼酿。

設計上榕酒,每個工序的職責都應該是明確而單一的,這樣才能達到最高的效率和流水線的可定制性故俐。

把這些概念映射到 RxJS想鹰,流水線就是 Observable(可觀察對象),工序就是 operator(操作符)药版,材料就是傳給每個 operator 的參數(shù)辑舷。

是不是感到很熟悉?沒錯槽片,它跟 MessageQueue 是一樣的模型惩妇,只是應用在不同的層次而已。在編程領域筐乳,這種現(xiàn)象隨處可見歌殃,善于發(fā)現(xiàn)并掌握這種現(xiàn)象,是你作為資深程序員能實現(xiàn)快速跨領域學習的根本保障蝙云。

相對于 Java 8 Stream氓皱,RxJS 比較特別的一點是它完全屏蔽了同步和異步之間的差異。也就是說勃刨,其中的 operator 不知道也不需要關心這個數(shù)據(jù)是同步傳過來的還是異步傳過來的波材。只要你遵循一些顯而易見的原則,你就可以一直用同步方式給數(shù)據(jù)身隐,之后即使要突然改成異步廷区,原有的代碼也不會被破壞。

事實上贾铝,我在 Angular 開發(fā)中經(jīng)常利用這種特性來加速開發(fā)隙轻。比如假設我最終需要從后端 API 獲取某些信息,在這個 API 開發(fā)好之前垢揩,我可以先在前端模擬出響應結果玖绿,進行后續(xù)開發(fā)。這時候叁巨,如果我用 Observable 的方式聲明數(shù)據(jù)源斑匪,那么雖然我目前用同步的方式提供數(shù)據(jù),但是將來我可以直接切換成 HTTP 數(shù)據(jù)源锋勺,而不用擔心破壞現(xiàn)有代碼蚀瘸。

細部原理

宏觀上的要點已經(jīng)講完了狡蝶,接下來我們快速過一遍微觀的。我只講要點贮勃,要想深入細節(jié)請參閱文中給出的參考資料牢酵。

Angular 模塊

Angular 模塊不同于 JavaScript 模塊,它是一個架構級的基礎設施衙猪,用來對應用進行宏觀拆分馍乙,硬化邊界,防止意外耦合垫释。

模塊的劃分主要基于業(yè)務領域的邊界丝格,而在開發(fā)組織形式上,也要和模塊劃分方式相互對齊棵譬,盡量讓每個模塊都有明確的負責人显蝌。

參見 https://angular.cn/guide/ngmodules

路由

傳統(tǒng)的路由功能完全是由后端提供的订咸,但是在單頁面應用中曼尊,在頁面中點擊 URL 時,將會首先被前端程序攔截脏嚷,如果前端程序能處理這個 URL骆撇,那就會直接在前端處理,而不會向后端發(fā)送這個請求父叙。

前端可以根據(jù)這個 URL 修改視圖神郊,給用戶與后端路由一樣的結果,但省去了網(wǎng)絡交互的過程趾唱,因此會顯得非秤咳椋快捷。

路由是業(yè)務功能的天然邊界甜癞,善用路由對于改善代碼結構和可維護性是很有幫助的夕晓。

在 Angular 中,路由還同時提供了惰性加載等特性悠咱,因此蒸辆,早期對路由進行合理規(guī)劃非常重要。不過也不用過于擔心乔煞,Angular 中重新劃分路由的代價并不高吁朦。

參見 https://angular.cn/guide/router#appendix-emlocationstrategyem-and-browser-url-styles

模板與視圖

你可以把模板看做 JSP渡贾,主要區(qū)別是 JSP 是后端渲染的,每次生成都需要一次網(wǎng)絡交互雄右,而模板是前端渲染的空骚,在瀏覽器中執(zhí)行模板編譯成的 JS 來改變外觀和響應事件纺讲。

模板語法

雖然看起來奇怪,但 [prop]囤屹、(click)熬甚、*ngFor 等模板語法中的特殊符號都是完全合法的 HTML 屬性名竟宋,實際上铁蹈,屬性名中只禁用各類空白字符、單雙引號等少數(shù)幾個顯而易見的無效字符(正則:[^\t\n\f \/>"'=])翻屈。

參見 https://www.w3.org/TR/2011/WD-html5-20110525/syntax.html#syntax-attribute-name智厌。

屬性與……屬性

由于歷史原因诲泌,英文的 Attribute 和 Property 都被譯為屬性,然而兩者是截然不同的铣鹏。Angular 中的常規(guī)綁定語法針對的都是 Property敷扫,只有 [attr.xxx] 綁定針對的是 Attribute。

參見 https://angular.cn/guide/template-syntax#html-attribute-vs-dom-property诚卸。

組件與指令

你可以把組件看做后端模板中的 taglib葵第,區(qū)別是它們運行在瀏覽器中而不是服務端。組件與指令在用途上的區(qū)別是合溺,組件充當搭建界面的磚塊卒密,它的地位和 HTML 元素并無區(qū)別;而指令用于為 HTML 元素(包括組件)添加能力或改變行為棠赛。

所以栅受,組件中不應該操縱 DOM,只應該關注視圖模型恭朗,而指令負責在模型和 DOM 之間建立聯(lián)系屏镊。指令應該是單一職責的,如果需要完成多個職責痰腮,請拆成多個指令附加到同一個元素上而芥。

服務與依賴注入

Angular 的服務與依賴注入和 Spring 中的很像,主要的區(qū)別是 Angular 是個樹狀的多級注入體系膀值,注入器樹是和組件樹一一對應的棍丐,當組件要查找特定的服務時,會從該組件逐級向上查找沧踏,直到根部歌逢。

這實際上是職責鏈模式。當前組件找不到某個服務時翘狱,就會委托給其父節(jié)點來查找秘案。和策略模式結合使用,組件就可以通過自己提供一個服務來替換父組件提供的服務,實現(xiàn)一種支持默認處理的邏輯阱高。

參見 https://angular.cn/guide/hierarchical-dependency-injection赚导。

image

表單與驗證

在前端程序中,驗證主要是為了用戶友好性赤惊,而不是安全吼旧。安全是后端的工作,不能因為前端做了驗證而放松未舟。

Angular 對表單提供了非常強力的支持圈暗。如果你的應用中存在大量表單、大型表單裕膀、可復用表單或交互比較復雜的表單员串,那么 Angular 的表單功能可以為你提供強大的助力。

Angular 的表單提供了不同層級的抽象魂角,讓你可以在開發(fā)中輕松分離開顯示昵济、校驗、報錯等不同的關注點野揪。也讓你可以先用文本框快速搭出一個表單访忿,將來再逐個把這些文本框替換成自定義編輯框,而不會破壞客戶代碼斯稳。

參見 https://angular.cn/guide/user-input海铆。

測試

Angular 對測試的支持非常全面,可以實現(xiàn)各個不同層次的測試挣惰。

但是不要因為拿到把這么好用的錘子就滿世界敲卧斟。要根據(jù)不同的價值需求去決定測什么不測什么。

別忘了每個 Angular 的類憎茂,無論服務珍语、組件、指令還是管道等竖幔,都是 POJO板乙,你可以用測 POJO 的方式測試它們,得到毫秒級反饋拳氢,而且這往往會更高效募逞。

參見 https://angular.cn/guide/testing。但要記撞銎馈:雖然 Angular 支持這么多種方式放接,但你不一定要用到這么多種方式。

安全

在 Angular 中留特,你不會無意間造成安全隱患纠脾。只要注意一點就夠了:DomSanitizer.bypassSecurityTrust* 要慎用玛瘸,務必確保傳給它的東西不可能被攻擊者定制,必要時請找安全專家推演乳乌。參見 https://angular.cn/guide/security#sanitization-and-security-contexts捧韵。

如果你在發(fā)起 POST 等請求時收到了 403 錯誤市咆,那可能是因為后端開啟了 CSRF 防護汉操。Angular 內(nèi)置了一個約定 —— 如果服務端 csrf token 的cookie名是 XSRF-TOKEN,并且能識別一個名叫 X-XSRF-TOKEN 的請求頭蒙兰,那么它就會自動幫你完成 CSRF 驗證磷瘤。當然,你也可以自定義這些名稱來適配后端搜变,參見 https://angular.cn/guide/http#configuring-custom-cookieheader-names采缚。

跨域與反向代理

本地開發(fā)時,前端有自己的服務器挠他,顯然無法與后端 API 服務器運行在同一個端口上扳抽,這樣就導致了跨域問題。要解決跨域問題殖侵,主要有 CORS 和反向代理這兩種方式贸呢。CORS 是標準化的,但是受瀏覽器兼容性的影響較大拢军;而反向代理則通過把 API “拉”到前端的同一個域下楞陷,從根本上消除了跨域訪問。

開發(fā)時茉唉,Angular CLI 內(nèi)置了對反向代理的支持固蛾;部署時,各個主流 Web 服務器都能很好地支持反向代理度陆。

一般項目中建議還是優(yōu)先使用反向代理的方式艾凯。

(圖片來自:http://t.cn/RgsWKEJ

雜談

你不必寫 CSS

很多后端初學前端時會被卡在 CSS 上,在心里喊一句 WTF懂傀。但實際上趾诗,在團隊開發(fā)中,你可能根本不必寫 CSS鸿竖。

現(xiàn)在已經(jīng)有了很多現(xiàn)成的 CSS 庫沧竟,比如已經(jīng)熟透的 Bootstrap,還有后起之秀 Material Design缚忧、Ant Design 等等悟泵。你只要能根據(jù)其表達的視覺含義,正確套用它們定義的 CSS 類就夠了闪水。盡量不要自己手寫 CSS糕非,否則可能反倒會給將來的頁面美化工作帶來困擾。

選好了基礎框架,并且和 UX 對齊之后朽肥,團隊中只需要一個 CSS 高手就能實現(xiàn)所有的全局性設計規(guī)則禁筏。對于全棧工程師來說,充其量只有對當前頁面中的少量元素進行定制時才需要寫 CSS衡招,況且還可以通過找人 pair 來解決偶爾碰到的難題篱昔。

全棧,讓設計更簡單

前后端技術各有所長始腾,有些事情用前端實現(xiàn)更簡單州刽,有些用后端實現(xiàn)更簡單。綜合考量前端技術和后端技術浪箭,往往可以產(chǎn)生更簡單穗椅、更優(yōu)秀的設計。廣度在業(yè)務開發(fā)中往往比深度有用奶栖,這也是全棧工程師的優(yōu)勢所在匹表。而團隊中的技術專家主要負責深度。

分工是動態(tài)的

技術專家或全棧工程師宣鄙,并不是什么榮譽頭銜袍镀,只是分工不同而已。

同一個項目上你可以同時擔任全棧工程師和技術專家框冀;這個項目你是全棧工程師流椒,下一個項目上也可能專門擔任技術專家。團隊的協(xié)作方式永遠是動態(tài)的明也、隨需應變的宣虾。

不用擔心全棧會限制你的技術深度,實際上温数,全棧對提高你的技術深度是有幫助的绣硝,因為很多技術的“根”都是互通的。

相信你的直覺

資深后端首先是一個資深程序員撑刺,你對于“應該如何”的期待鹉胖,很可能是對的。如果你覺得 Angular 應該有某項功能或某種設計够傍,它很可能確實有甫菠。去 Stackoverflow 搜一下,找找你的答案冕屯,這是你成為高級 Angular 程序員的捷徑寂诱。

萬法歸一

形容某人聰明時經(jīng)常說“萬法皆通”,實際上“萬法皆通”不如“一法通而萬法通”安聘。很多技術之間的相似程度超出你的想象痰洒,這些相似的部分其實就是技術的核心瓢棒。用萬法歸一的思路去學習總結,會給你帶來真正的提高丘喻。

資料 & 學習指南

學習 Angular 的最佳資料是它的官方文檔脯宿,它無論是從準確、全面泉粉,還是及時性等方面都是最佳的连霉。

它的英文文檔站是 https://angular.io,中文文檔站是 https://angular.cn搀继,這是由我和另外兩位社區(qū)志愿者共同翻譯的窘面,期間還得到了很多社區(qū)志愿者的支持翠语。中文文檔和英文文檔至少在每個大版本都會進行一次同步翻譯叽躯。雖然時間有限導致語言上還有粗糙之處,不過你可以相信它的技術準確度是沒問題的肌括。

閱讀時点骑,請先閱讀架構概覽 https://angular.cn/guide/architecture,然后閱讀教程 https://angular.cn/tutorial(有經(jīng)驗的程序員不需要跟著敲代碼谍夭,如果時間緊也可跳過)黑滴,最后閱讀風格指南 https://angular.cn/guide/styleguide。風格指南很重要紧索,不用記住袁辈,但務必通讀一遍,有點印象供將來查閱即可珠漂。

文檔站中還提供了 API 參考手冊晚缩,它提供了簡單快速的站內(nèi)搜索功能,需要了解哪些細節(jié)時到里面查就可以了媳危。

另外荞彼,ng-zorro 組件庫的一位開發(fā)者還整理了一份不完全指南,包括中英文資料:https://zhuanlan.zhihu.com/p/36385830待笑。

文/ThoughtWorks 汪志成

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸣皂,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子暮蹂,更是在濱河造成了極大的恐慌寞缝,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仰泻,死亡現(xiàn)場離奇詭異荆陆,居然都是意外死亡,警方通過查閱死者的電腦和手機我纪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門慎宾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丐吓,“玉大人,你說我怎么就攤上這事趟据∪纾” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵汹碱,是天一觀的道長粘衬。 經(jīng)常有香客問我,道長咳促,這世上最難降的妖魔是什么稚新? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮跪腹,結果婚禮上褂删,老公的妹妹穿的比我還像新娘。我一直安慰自己冲茸,他們只是感情好屯阀,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著轴术,像睡著了一般难衰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逗栽,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天盖袭,我揣著相機與錄音,去河邊找鬼彼宠。 笑死鳄虱,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的兵志。 我是一名探鬼主播醇蝴,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼想罕!你這毒婦竟也來了悠栓?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤按价,失蹤者是張志新(化名)和其女友劉穎惭适,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體楼镐,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡癞志,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了框产。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凄杯。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡错洁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戒突,到底是詐尸還是另有隱情屯碴,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布膊存,位于F島的核電站导而,受9級特大地震影響,放射性物質發(fā)生泄漏隔崎。R本人自食惡果不足惜今艺,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爵卒。 院中可真熱鬧虚缎,春花似錦、人聲如沸技潘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽享幽。三九已至,卻和暖如春拾弃,著一層夾襖步出監(jiān)牢的瞬間值桩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工豪椿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奔坟,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓搭盾,卻偏偏與公主長得像咳秉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鸯隅,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容