前端的工作就是切板,這已經是將近十年前的觀念,隨著現代硬體設備越來越強、網路速度越來越快,瀏覽器能做的事情,已經比便利商店提供的服務還要多樣化,這也造成了前端要掌控的狀態越來越複雜,當開發的專案複雜度大於某個量級的時候,維護起來會變得異常困難,這時候開始有各種前端框架跳出來,想要解決這個事情,最有名的就屬 angular, react, vue 這三個了,這三個被工程師們譽為前端三大框架,而我們今天的主題就是 react。
除了以往的樣式特效以外,現在的前端瀏覽器能做的事情有:
* 3D 製圖
* 遊戲
* 機器學習
* 接收麥克風音訊
* 接收鏡頭的視訊
* VR
* AR
要了解這個問題,最快的方式就是去看 React 的官網,畢竟沒有人說的話會比官網還權威,一進到官網就能看到官方給自己下的定義:
A JavaScript library for building user interfaces(創造使用者介面的一個 javascript 函式庫)
有的同學可能就納悶了,原生 js 不是也能做到創造 DOM,或是修改 DOM 的 class 之類的介面處理嘛,其實 js 的確能做到這些事情,畢竟九成以上的 library 都是用 js 寫的,使用這些 library 為的除了不重複造輪子之外,不外乎就是為了更好的開發體驗,
假如現在有一段 html,我們需要實作 changeFooText()
的功能
<!--html-->
<div id ='fooId'>foo</div>
<button onclick='changeFooText()'>click me</button>
假設現在已經有一個寫好的 function 叫做 getText
,它會根據商業邏輯回傳一個字串,需求是希望點擊 button 後,會去 call getTextApi 並用回傳值,修改上面的foo,那麼我們該怎麼實作這個需求呢?若是寫原生的 js 我們可能會這樣寫
//純 javascript
function changeFooText(){
const fooDom = document.getElementById('fooId');
let bar = getText('bar');
fooDom.innerText=bar;
}
首先要去取得 DOM 再去 call function 來修改它的內容,看起來是簡單又合理的操作,把以上程式碼轉換成 react 的話,大概會長得像是下面這個樣子
// react
class Demo extends React.Component {
state = { text: "foo" };
changeFooText = function(){
let bar = getText('bar');
this.setState({ text: bar });
}
render() {
return (
<>
<div>{this.state.text}</div>
<button
onClick={changeFooText}
>
click me
</button>
</>
);
}
}
如果有看不懂的部分可以先不用理會沒有關係,後面幾個章節會詳細解釋 react 基本語法,首先要注意到的是原本 <div id ='fooId'>foo</div>
中的 foo
文字,被替換成了 {this.state.text}
而這裡就會對應到上面 { text: "foo" };
中的 foo ,如此一來只要修改 state.text,畫面就會改變了,所以在 changeFooText
中,我們就不用再去 get DOM,而是直接去更改 state 就好,不過這個範例比較沒什麼 feel,實際上如果你的專案都是類似這種規模的場景,並沒有使用 react 的意義,我們可以稍微把上面這個案例,稍微變得複雜一點點
細心的讀者可能會發現 html 檔消失了,然後被寫在 js 檔之中,其實那個東西不是 html 而是一個叫做 jsx 的東西,不過不知道這是什麼的同學可以先想像成 react 把 html 寫在 js 裡面了,我們後面幾個章節會在講解 jsx
跟剛剛一樣我們有一份 html,這次需要實作 changeFoo()
的功能
<!--html-->
<div id ='foo'>
<div id ='fooId'>foo</div>
<div id ='fooTitle'>foo</div>
<div id ='fooDesc'>foo</div>
<div id ='fooNumber'>foo</div>
<div id ='fooItem'>foo</div>
<div id ='fooHead'>foo</div>
<div id ='fooBody'>foo</div>
</div>
<button onclick='changeFoo()'>click me</button>
我們擁有另一個 function getInfo
,不同的是它這次會回傳的是一個 Object,需要根據這個 Object 來修改裡面全部的資料,不過我們完全可以依樣畫葫蘆,來完成這個需求
// 純 javascript
function changeFoo(){
const fooIdDom = document.getElementById('fooId');
const fooTitleDom = document.getElementById('fooTitle');
const fooDescDom = document.getElementById('fooDesc');
const fooNumberDom = document.getElementById('fooNumber');
const fooItemDom = document.getElementById('fooItem');
const fooHeadDom = document.getElementById('fooHead');
const fooBodyDom = document.getElementById('fooBody');
let barInfo = getInfo('bar');
fooIdDom.innerText = barInfo.id;
fooTitleDom.innerText = barInfo.title;
fooDescDom.innerText = barInfo.desc;
fooNumberDom.innerText = barInfo.number;
fooItemDom.innerText = barInfo.item;
fooHeadDom.innerText = barInfo.head;
fooBodyDom.innerText = barInfo.body;
}
其實整體的邏輯跟剛剛一樣,但是因為我們要改很多不同的 DOM 所以就要 get 每一個 DOM,再對每一個 DOM 去做操作,看起來做了很多相同的事情,再來我們來看看 react 的表現
// react
class Demo extends React.Component {
state = {
fooId: "foo",
fooTitle: "foo",
fooDesc: "foo",
fooNumber: "foo",
fooItem: "foo",
fooHead: "foo",
fooBody: "foo",
};
changeFoo = function(){
let fooInfo = getFooApi('bar');
this.setState({
fooId: fooInfo.id,
fooTitle: fooInfo.title,
fooDesc: fooInfo.desc,
fooNumber: fooInfo.number,
fooItem: fooInfo.item,
fooHead: fooInfo.head,
fooBody: fooInfo.body,
});
}
render() {
return (
<>
<div>
<div>{this.state.fooId}</div>
<div>{this.state.fooTitle}</div>
<div>{this.state.fooDesc}</div>
<div>{this.state.fooNumber}</div>
<div>{this.state.fooItem}</div>
<div>{this.state.fooHead}</div>
<div>{this.state.fooBody}</div>
</div>
<button
onClick={changeFoo}
>
click me
</button>
</div>
);
}
}
開發者只需要確認資料是對的,然後把他塞到 state 裡面,不需要去 get DOM,react 就會幫你畫好畫面了,開發體驗上,react 明顯略勝一籌,越複雜的專案,使用 react 所帶來的好處就越明顯。
我在 codeSandBox 開了一個最純粹的 react 專案,非常推薦沒玩過的同學可以自己點開來改改看 state ,絕對能有更多的收穫。