1. React 福音
當我們的團隊開始尋找一個合适的前端架構的時候,我們考慮了許多選擇,最後留下兩個選項 —— Angular 和 React。
Angular 是目前為止最成熟的方案:它擁有一個龐大的社群,你可以為大部分應用場景找到合适的第三方子產品。
React 也很有競争力,它以 JavaScript 為中心的設計看起來很有前途,而且它性能很好。雖然它還是 Beta 版本,但是 “由Facebook團隊開發的” 這一點給它的競争力加分。
我們決定給 React 一個機會,選擇了使用它。
最初使用 React 讓人感覺棒極了,我們可以用 JavaScript 來做一切:展現一段 HTML,通過周遊數組渲染一個清單,優雅地改變一個變量的值,然後看着它通過 props 傳播到各處,更新要更新的内容到可複用元件裡,然後一切就緒了,沒有一坨一坨的代碼,隻有真正的停下來思考。React 解決了我們在團隊開發中編寫可維護代碼的訴求。
2. React + Flux = ♥
但沿着這條路走下去,我們發現并不是一切都很美好。我們遇到的第一個大挑戰就曾讓我們考慮是否應該放棄 React —— 我們陷入了回調迷宮。
由于 React 的單向資料流性質,如果子元件需要更新父元件的狀态,父元件就要傳一個回調函數給它。這咋看起來沒有什麼大不了的,然而如果你的元件要更新 root 元件的狀态,你就不得不将 “this.props.updateCallback” 沿着資料流一層一層傳遞下來。
盡管如此,我們喜歡 React,繼續使用它完成我們的工作。通過努力,我們找到了 Flux,它是一種規範化單向資料流的架構思想。它由四個主要元素構成。
- Store: 負責存儲資料和應用狀态。
- Action: 觸發狀态改變。
- Dispatcher: 管理 action 并将它們導向對應的 store。
- View: 展現 store 中的資料,派發 action - 這塊是 React 中已有的。
采用 Flux,我們就不用将狀态儲存在 root 元件中,然後将 update 回調一層層傳遞給它的子元件。React 元件通過 store 直接獲得資料,通過調用 action 來改變狀态:這樣簡單、優雅,不會讓你抓狂。Flux 補充了可預測的行為和一些标準到被 React 架構限制的代碼中。
3. 狂野的 Angular 出場……
……它采用以 HTML 為中心的代碼且并不超有效。
最近,我開始參與一個 Angular 項目。我加入的時候這個項目已經完成了很大一部分了,是以不得不用 Angular,沒有回頭路。作為一個忠實的 React 開發者,我吐槽 Angular。當我開始寫第一行 Angular 代碼的時候,我就真心詛咒它。這就是所謂的:如果你愛 React,那你就恨 Angular。
我不能自欺欺人,在一開始,我寫 Angular 代碼一點也不開心。将架構定義的屬性(或者,更恰當地說法是 directives)寫入到 HTML 中的做法讓我感覺很不爽。我得費很大勁才能實作很簡單的功能,比如改變 URL 的時候不重新加載 controller 或者渲染基礎模闆。
當我在表單中遇到一個由于 ngIf directive 建立一個新的子域而導緻的問題時,我處理起來還是很費勁。還有當我想要從一個準備發送給伺服器的 JSON 中移除一些空白字段時,我發現 UI 中對應的資料也被一并移除了 —— 丫的雙向綁定 ╮(╯▽╰)╭。還有當我想要使用 ngShow 和 ngHide 來顯示一個 HTML 塊同時隐藏另一個 HTML 塊時,在一瞬間,兩者同時顯示了。我明白許多問題是我自己的問題,而我想要指出的是,Angular是不可預測的,使用它的時候會遇上各種各樣的坑。
當然,Angular 還是善于處理很多事情的。内建的 HTTP 請求子產品 非常棒,對 promise 的支援也很好。另一個我無法吐槽的好東西是:内建的表單控制器,它為 input 字段提供了預設的格式化、解析和校驗,而且還提供了一個很好的插件用來展示錯誤資訊。
使用 Angular 也能讓開發團隊與頁面制作團隊協同工作變得更簡單。在我們團隊,有專門的頁面重構工程師負責寫 HTML 和 CSS,Angular 能讓我們的工作無縫對接:重構工程師負責 HTML 和一些額外的标簽,我負責處理邏輯。如果我們使用的是 React,那麼至少讓重構工程師寫元件會是一個挑戰,要麼得讓他學會寫基本的 JSX,要麼我就隻能自己将他寫的 HTML 複制粘貼到 JSX 中。
還記得前面提到的 URL 替換和模闆渲染問題嗎?其實沒關系,人們通常使用第三方的路由庫(ui-router)它們比标準的 (ngRoute)要好用。最後,Angular 也沒有我之前認為的那樣糟糕。之前的大多數抱怨要麼是因為我習慣了 React 思維,要麼是我還不夠專業。
4. 總結: AngularJS 與 ReactJS
React 使用原生 JavaScript 函數讓開發者可以建立一個有固定生命周期的、單向資料流的可複用元件。React 與 Flux 架構(或者受 Flux 啟發而産生的其他架構,比如 Redux)相結合,能讓團隊長期維護一個項目變得更加容易,使用它不用擔心解決一個 bug 會引入更多新 bug。但是,如果你的團隊有專門寫 HTML 和 CSS 的人,React 會帶來額外的學習成本,因為它改變了傳統的開發流程。而且 React 的效果還非常依賴你選擇的組成你的應用的子產品。
另一方面,Angular 專注于設計簡單的雙向資料綁定,當你改變 controller scope 中的内容,變化将會被自動地同步到UI(效果如同魔法般)。它自認為節省了配置的時間,開發者不用像傳統開發模式那樣考慮用各種設計模式組織代碼然後從上百種可選的方案中選出一個核心子產品。使用雙向綁定為開發帶來了便利,然而它也容易在長期維護的過程中由于修改部分代碼而産生不可預期的 bug,尤其是那些在過去的幾個月中沒有再動過的代碼。
那麼,我從頭開始建立 app 的首選方案是什麼呢?
從長遠而言,我個人傾向于選擇 React,使用 Redux 架構,使用 Axios 支援 promise-ready 的 HTTP 請求,以及使用 react-router 處理路由。