2016 年の前端,瘋什麼 ReactJS?

Jason Chung
前端魔法研究室
8 min readMar 10, 2016

相信這一年你一定常常聽到 React 這個關鍵字。
「ReactJS 顛覆了前端世界…」
「React Native 快速打造原生手機應用程式…」
「React blah, blah, blah…」

不過,在你的印象中,React 是什麼呢?

誒,先別立馬去估狗呀!為了讓你繼續看下去,我就在這裡直接告訴你答案吧:ReactJS 是一個讓你便於建構 UI 的程式庫;而且,只有 UI

「啊?聽起來弱弱的!」
「UI,不就是 HTML, CSS 嗎?」

恩…沒錯,你這樣想是沒錯的。

先讓我們倒回 Facebook 當初靈機一動產生 React 的時候。我想當你知道那位創始者的甘苦談,你應該會更了解 React 的價值。

回溯到還在娘胎的 React

在很久很久以前,差不多 2010 年時,Facebook 的開發團隊發現他們渲染頁面的引擎越來越不堪負荷。

可以想像的是,由於功能越多,觸發頁面的事件越多,前端資料狀態的變化也越頻繁,因此改變 DOM 結構也會越頻繁。我想你應該要知道的是 HTML DOM 是一個很大的樹狀資料,每當一個事件發生,而需要進行新增、修改、刪除時,底層的程式就必須先從這一棵大樹中,一直深入,再深入,直到找到某一片你有興趣的葉子,可想而知這是多麽大的工程!

而另外一個問題是,他們發現前端的程式越來越難維護,我想應該是因為由事件觸發的程式,很難進行封裝和模組化。就像你用某一個 jQuery 套件時,你可能需要先在你的 HTML 上加入相對應的 class 或 id 才行,而到了程式非常複雜的時候,你根本不知道這一個 class 到底背後的行為是什麼,而且也會患有不敢修改的恐懼症!

所以,為了要解決
1. 頻繁改變 DOM 是很耗效能的
2. 前端程式很難封裝和模組化

React 就由此產生了,而他的母親是 FB 的工程師 Jordan Walke
2011 年時,React 開始實作來解決上述兩個議題。
2013 年時,Instagram 使用 React 進行改版,也在同年,React 在 Github 上開放程式碼。

一. 設計元件,不是模板

讓我們先來了解 React 怎麼解決很難封裝和模組化這個議題。

我們先來看看以往的 jQuery:

/**
* index.html
*/
<div id="output"></div>
/**
* main.js
*/
$('#output').html('hello, world');

如果 jQuery 用在複雜一點的應用程式,就會出現 2010 年前 FB 工程師遇到的問題 — 難以維護。單單只看 index.html 這個檔案,你完全猜測不出來 output 這個 class 到底隱含了什麼行為。

因此,我們看看一年前正夯的 AngularJS 如何解決這個議題。

/**
* index.html
*/
<body ng-controller="MainCtrl">
<div ng-model="value"></div>
</body>
/**
* MainCtrl.js
*/
app.controller('MainCtrl', ($scope) => {
$scope.value = 'hello, world';
});

在 index.html 中,如果你學過 AngularJS,你會很明確的了解 div 的資料由哪裡來;如果你還不認識它,你或許可以猜到 div 的資料就是在一支叫 MainCtrl 的檔案中,且由裡面的 $scope.value 去定義。

不過,如果你真的有開發過前端或是手機應用程式,你應該會常常在 Layout 模板的檔案,和相對應渲染頁面邏輯的檔案兩邊跑。

你會好奇為什麼不放在一起呢?有些前輩會跟你說,這是「關注點分離」。

但是事實上,「顯示邏輯」和「模板」有很強的一致性,他們不應該被拆開。而擁有這兩者的物件,我們稱做他為元件。

/*
* HelloWorld.js
*/
class HelloWorld extends Component {
render() {
const value = 'hello, world';
return <div>{value}</div>;
}
}

你說不定會說這是多髒的程式,JS 語法和類 HTML 語法混雜在一起,等到程式長大了該怎麼辦?不要忘記的是,你可以將元件拆細一點,再將它們組合起來,或者重複利用。至於 JS 和 HTML 混雜在一起這件事,我們通常會把這兩種技術看待為一件事來開發,那麼為什麼需要分離呢?!

二. 一律重繪

你應該知道一個應用程式的狀態會非常多,而且會頻繁的變化。如果我們傾聽某一個事件,就要針對這一個狀態進行 DOM 的處理,那你將會越來越辛苦。

而在 React 中,他將這一件事的處理,拆成兩個關注點:
1. 當你傾聽某一個事件,你會去改狀態的資料
2. 針對所有資料,你來進行排版

這就不容易出錯了,因為你在乎的兩件事情「改變資料」和「排版」分開來了。而一律重繪是指只要資料變動一次,我就根據你給我的版型,重新的填充資料,並且顯示給使用者。

你或許會好奇,那每次重繪,不會很耗效能嗎?這就是下一篇要講的事情了。

三. Virtual DOM

我們知道改變 DOM 是很耗效能的一件事,而一律重繪將會改變所有的 DOM,但是如果開發者跟 DOM 中間有一個人,可以幫我們改變最小幅度的 DOM 那該有多好。

這個人就是 Virtual DOM,一律重繪改的事實上是記憶體中的 DOM 物件,而 React 會在根據舊狀態和新狀態的排版和資料進行比對,將確切有需要更動的 DOM 真實反映在瀏覽器的 DOM 上。

這種比對和效能的調校不會是你感興趣的,React 幫你做了。你只需要了解你應用程式的排版是怎麼樣就好了。

說說 ReactJS 的優點

  1. 你可以在一個檔案中,看出元件的排版和行為。
    你通常會一致性的看待這兩件事,那為什麼不就在一個檔案中就好呢?
  2. 「資料的操作」和「排版」是需要被看待為兩件事處理,一律重繪,幫助你分別關注這兩件事情。

說說 ReactJS 的缺點

  1. React 只有 UI,在你真正用在應用程式上時,你會發現它缺了許多東西:前端路由、資料流、AJAX 和非同步的 Promise 功能等。

那麼,ReactJS 和 AngularJS 的差別呢?

我想你應該會問這一個問題,就跟當初我在考慮是不是要跳進 React 的坑時,也曾經冒出這個問題,因為我想知道到底有沒有轉換陣營的必要,總不能走個冤枉路。

不過,答案是如果單單是 React 和 Angular 去比較,你會發現 React 真的就只是 View 這一層而已;而 Angular 是一個 Model-View-Whatever 的框架,它完整的處理了與後端抓資料的 AJAX、前端的路由、非同步的 Promise 功能、two-way data binding 資料流等。

所以當你用 React 開發一個複雜的前端應用程式時,你需要其他的程式庫去輔助你完成 React 沒提供給你的東西。這對一個初學者來說,就像是好大好大的一片阻礙的牆,沒有了強大的靠山似的。

不過,經過了 3 年的 React,已經從簡單的程式庫發展成龐大的「生態系統」,有越來越多相對應的第三方程式庫去完成各式各樣的需求。

因此最大的差別,我覺得是看你喜歡「元件式」還是「模板式」的開發體驗和思維。

那麼,我該使用 React 嗎?

我會推薦你應該要,因為我愛上它了。

但是我認為你應該想一想你是要拿來開發什麼,如果你只是要開發狀態變化不是很大的頁面,譬如 Landing Page,那我認為你可能寫了一堆 React 程式,但只會越來越抱怨你幹嘛繞了一大圈寫這些功能。

但是如果是大型應用程式,複雜的事件和狀態變化,而且往後如果是你維護的話。就用它吧:)

重點整理

  1. ReactJS 是一個讓你便於建構 UI 的程式庫;而且,只有 UI。
  2. ReactJS 的三大特色:
    一. 設計元件,不是模板
    二. 一律重繪
    三. Virtual DOM
  3. ReactJS 的優點:好維護。

最後補充

之後我會開始寫「快速體驗 ReactJS」課程系列,大概會有以下內容:

1. 用元件的思維設計應用程式
2. 從印出 hello, world 開始
3. 撰寫第一個元件
4. 組合多個元件
5. 傳遞元件參數
6. 設計防呆、可重複使用的元件
7. 動態產生多個元件
8. 管理元件的內部狀態
9. 使用表單元件
10. 了解元件的生命週期

我會盡我所能幫助你們用最短的時間,快速瞭解 ReactJS 是什麼。

然後,我需要大家的幫助,因為正在趕稿,如果有錯字,或是可以讓文章更簡潔一點的話,都拜託在下方留言建議給我。等往後線上教學教材真的出版,會隆重列上各位的大名,感謝各位大大:)

你應該會想看的其他參考

文章或簡報

  1. ReactJS for Stupid People
  2. What is React
  3. React: Rethinking Best Practices
  4. 從「學習一次、隨處應用」 談 React Native 帶來的開發典範轉移

如果你喜歡我的內容,歡迎「點此分享」到臉書給更多朋友;或是按五次下方的 LikeButton 給我個讚吧!

--

--