初識React
React 是一個采用聲明式,高效且靈活的,用來構(gòu)建用戶界面的框架。React 當(dāng)中包含了一些不同的組件。
從使用 React.Component 開始,下面自定義一個組件

開發(fā)中一般都會使用一種名為 JSX 的語法擴展來跟方便地書寫;在 JSX 中可以任意使用 JavaScript 表達式,只需要用一個大括號把表達式括起來;
要使用該組件時,通過這種標(biāo)簽語法: <ShoppingList name="Mark" />
來使用我們上面聲明的組件。
從#字棋游戲?qū)W習(xí)React
Square 組件代表一個單獨的 <button>,Board 組件包含了9個Square,也就是棋盤的9個格子。Game 組件則為我們即將要編寫的代碼預(yù)留了一些位置?,F(xiàn)在這幾個組件都是不具備任何的交互功能的。
1、通過props傳遞數(shù)據(jù)
Borad組件
class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />;
}
render() {
const status = 'Next player: X';
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
在 Board 組件的 renderSquare 方法中,傳遞一個名為 value 的 prop 到 Square 當(dāng)中:


添加交互功能

傳給 onClick屬性一個函數(shù)方法,這里使用了 JavaScript 當(dāng)中一種新的名為“箭頭函數(shù)”的語法,
注意:假如寫的是 onClick={alert('click')} ,警示框是會立即彈出(而不是點擊之后再彈出)
組件狀態(tài)
一個組件會接受名為 props 的參數(shù);
在 React 組件的構(gòu)造方法 constructor 中,你可以通過 this.state 為該組件設(shè)置自身的狀態(tài)數(shù)據(jù)。下面以Square為例:

必須調(diào)用 super(); 方法,才能在繼承父類的子類中正確獲取到類型的 this 。
更改組件狀態(tài)
通過點擊事件觸發(fā) state 的改變,來更新棋盤格子顯示的內(nèi)容。

每當(dāng) this.setState 方法被觸發(fā)時,組件都會開始準(zhǔn)備更新。React 通過比較變化,來更新組件中改變了的內(nèi)容。當(dāng)組件重新渲染時,this.state.value 會變成 'X' ,也就能在格子里看到 X 的字樣。
狀態(tài)優(yōu)化
現(xiàn)在,狀態(tài)是獨立保存在Borad上的每個 Square 組件當(dāng)中的,但這種數(shù)據(jù)的獨立使得無法對所有數(shù)據(jù)進行整體分析。
最好的解決方式是,直接將所有的 state 狀態(tài)數(shù)據(jù)存儲在 Board 組件當(dāng)中。之后 Board 組件可以將這些數(shù)據(jù)傳遞給各個 Square 組件。
@:當(dāng)你遇到需要同時獲取多個子組件數(shù)據(jù),或兩個組件之間需要相互通訊的情況,把子組件的 state 數(shù)據(jù)提升至其共同的父組件當(dāng)中保存。之后父組件可以通過 props 將狀態(tài)數(shù)據(jù)傳遞到子組件當(dāng)中。這樣應(yīng)用當(dāng)中的狀態(tài)數(shù)據(jù)就能夠更方便地交流共享了。
1、修改Board 組件
現(xiàn)在,在 Board 組件的構(gòu)造函數(shù)中,初始化一個包含9個空值的數(shù)組作為狀態(tài)數(shù)據(jù),并將這個9個元素分別傳遞到對應(yīng)的9個 Square 組件當(dāng)中:

并在 value 屬性中傳遞對應(yīng) state 數(shù)組元素的值給Square組件:

現(xiàn)在每個格子當(dāng)中的數(shù)據(jù)是存儲在整個棋盤當(dāng)中的,我們需要讓格子組件能夠修改整個棋盤組件數(shù)據(jù)的內(nèi)容。下面,就來修改格子的點擊事件處理函數(shù)——通過 props 傳遞一個父組件中的函數(shù)到子組件Square 中。

現(xiàn)在,從 Board 組件向 Square 組件中傳遞了兩個 props 參數(shù):value 和 onClick
2、修改Square組件
this.state.value 替換為 this.props.value、this.setState() 替換為 this.props.onClick()

現(xiàn)在,每次格子被點擊時,就會觸發(fā)傳入的 onClick 方法,也就是觸發(fā)Borad中的handleClick方法。下面,回到Borad中,編寫 handleClick 方法:
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = 'X';
this.setState({squares: squares});
}
@ :其中使用了 .slice() 方法,來將之前的數(shù)組數(shù)據(jù)淺拷貝到了一個新的數(shù)組中,而不是修改已有的數(shù)組。這種做法對后續(xù)工作非常有益,可以輕松地實現(xiàn) 撤銷、重做以及時間旅行,記錄判斷等。
現(xiàn)在,格子組件 Square 不再擁有自身的狀態(tài)數(shù)據(jù)了。它從父組件 Board 接受數(shù)據(jù),并且當(dāng)自己被點擊時通知觸發(fā)父組件改變狀態(tài)數(shù)據(jù),我們稱這類的組件為:受控組件。
函數(shù)定義組件
由于組件 Square變成了受控組件,那么就可以去掉它的構(gòu)造函數(shù)了。只需簡單寫一個以 props 為參數(shù)的 function ,返回 JSX 元素就搞定了。

注意:props.onClick后不加(),否則該方法會在 Square 組件渲染時被直接觸發(fā)!
游戲完善
-
輪流落子
X 和 O 輪流落子。添加一個狀態(tài)標(biāo)志xIsNext,根據(jù)此標(biāo)志決定是X還O
QQ.png
每走一步棋,都需要切換 xIsNext 的值,在handleClick方法中:

render 方法里提示當(dāng)前執(zhí)子的一方:

Key
當(dāng)你在 React 當(dāng)中渲染列表項時,React 都會試著存儲對應(yīng)每個單獨項的相關(guān)信息。必須為列表中的每一項添加一個 key 作為唯一的標(biāo)識符。
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
1、key 是 React 中使用的一種特殊的屬性,除此之外還有 ref 屬性;
2、當(dāng)元素被創(chuàng)建時,React 會將元素的 key 值和對應(yīng)元素綁定,存儲起來。但無法通過 this.props.key 獲取到 key 的值;
3、React 會自動的,在判斷元素更新時使用 key ,而組件自己是無法獲取到 key 的。
4、組件的 keys 值并不需要在全局都保證唯一,只需要在當(dāng)前的節(jié)點里保證唯一即可。
@ 只要你想在列表中對項目進行重新排列、添加或刪除,強烈建議你在渲染列表項時添加 keys 值。 假如沒有現(xiàn)成可以作為唯一 key 值的數(shù)據(jù)使用的話,你可能需要考慮重新組織設(shè)計你的數(shù)據(jù)了。
當(dāng)一個列表被重新渲染時,React 會根據(jù)較新的元素內(nèi)容依據(jù)相應(yīng)的 key 值來匹配之前的元素內(nèi)容。當(dāng)一個新的 key 值添加到列表當(dāng)中時,表示有一個組件被創(chuàng)建;被刪除時表示有一個組件被銷毀。Key 值可以讓 React 明確標(biāo)識每個組件,這樣它才能在每次重新渲染時保有對應(yīng)的狀態(tài)數(shù)據(jù)。假如你去改變某個組件的 key 值的話,它會在下次渲染時被銷毀并當(dāng)作新的組件重新渲染進來。
