2016 年の前端,瘋什麼 ReactJS?
相信這一年你一定常常聽到 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 的優點
- 你可以在一個檔案中,看出元件的排版和行為。
你通常會一致性的看待這兩件事,那為什麼不就在一個檔案中就好呢? - 「資料的操作」和「排版」是需要被看待為兩件事處理,一律重繪,幫助你分別關注這兩件事情。
說說 ReactJS 的缺點
- 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 程式,但只會越來越抱怨你幹嘛繞了一大圈寫這些功能。
但是如果是大型應用程式,複雜的事件和狀態變化,而且往後如果是你維護的話。就用它吧:)
重點整理
- ReactJS 是一個讓你便於建構 UI 的程式庫;而且,只有 UI。
- ReactJS 的三大特色:
一. 設計元件,不是模板
二. 一律重繪
三. Virtual DOM - ReactJS 的優點:好維護。
最後補充
之後我會開始寫「快速體驗 ReactJS」課程系列,大概會有以下內容:
1. 用元件的思維設計應用程式
2. 從印出 hello, world 開始
3. 撰寫第一個元件
4. 組合多個元件
5. 傳遞元件參數
6. 設計防呆、可重複使用的元件
7. 動態產生多個元件
8. 管理元件的內部狀態
9. 使用表單元件
10. 了解元件的生命週期
我會盡我所能幫助你們用最短的時間,快速瞭解 ReactJS 是什麼。
然後,我需要大家的幫助,因為正在趕稿,如果有錯字,或是可以讓文章更簡潔一點的話,都拜託在下方留言建議給我。等往後線上教學教材真的出版,會隆重列上各位的大名,感謝各位大大:)
你應該會想看的其他參考
文章或簡報
如果你喜歡我的內容,歡迎「點此分享」到臉書給更多朋友;或是按五次下方的 LikeButton 給我個讚吧!