太長不讀版:
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赚导。
表單與驗證
在前端程序中,驗證主要是為了用戶友好性赤惊,而不是安全吼旧。安全是后端的工作,不能因為前端做了驗證而放松未舟。
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 汪志成