react 學習1
React 是什麼?
React 是一個採用宣告式,高效而且靈活的用來構建使用者介面的框架。
狀態提升
當你遇到需要同時獲取多個子元件資料,或者兩個元件之間需要相互通訊的情況時,把子元件的 state 資料提升至其共同的父元件當中儲存。之後父元件可以通過 props 將狀態資料傳遞到子元件當中。
受控元件
子元件 不再擁有自身的狀態資料了,從福罪案接受資料並將資料要改變的事件通知父元件改變狀態資料,我們成為受控元件
在寫元件的時候 儘量把元件寫成無狀態的受控元件 把資料放在父元件裡 這樣利於資料維護
但是這樣就會牽扯到元件之間的相互通訊,如果多個元件改變同一個資料的時候 就會相互影響,為了避免這樣的影響,就需要 淺拷貝——不可變性
改變應用資料的方式一般分為兩種。第一種是直接修改已有的變數的值。第二種則是將已有的變數替換為一個新的變數。
直接修改資料
var player = {score: 1, name: 'Jeff'};
player.score = 2;
// Now player is {score: 2, name: 'Jeff'}
替換修改資料
var player = {score: 1, name: 'Jeff'}; var newPlayer = Object.assign({}, player, {score: 2}); // Now player is unchanged, but newPlayer is {score: 2, name: 'Jeff'} // 或者使用最新的物件分隔符語法,你可以這麼寫: // var newPlayer = {...player, score: 2};
通過這樣的方式,我們可以得到以下幾點好處:
1.實現 撤銷/重做 以及時間旅行。 因為不改變已有的資料 所以我們在需要的時候隨時切換回歷史資料
2.記錄變化 每次我們都返回一個新的物件 所以要判斷對想是否被替換 那麼其中的資料肯定就改變了,檢查到替換之後 就可以執行對應的操作
編寫元件最好編寫 純元件 pure components 對於效能優化可以用 shouldComponentUpdate()
key
是 React 當中使用的一種特殊的屬性(除此之外還有 ref
key
值和對應元素繫結儲存起來。儘管 key
看起來像是 props 的一部分,可是事實上我們無法通過 this.props.key
獲取到 key
的值。React 會自動的在判斷元素更新時使用 key
,而元件自己是無法獲取到 key
的。
當一個列表被重新渲染時,React 會根據較新的元素內容依據相應的 key 值來匹配之前的元素內容。當一個新的 key 值新增到列表當中時,表示有一個元件被建立;被刪除時表示有一個元件被銷燬。Key 值可以讓 React 明確標識每個元件,這樣它才能在每次重新渲染時保有對應的狀態資料。假如你去改變某個元件的 key 值的話,它會在下次渲染時被銷燬並當作新的元件重新渲染進來。
強烈建議你在渲染列表項時新增 keys 值。 假如你沒有現成可以作為唯一 key 值的資料使用的話,你可能需要考慮重新組織設計你的資料了
根據官網寫的遊戲demo
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// Square 元件代表一個單獨的 <button>
class Square extends React.Component {
constructor() {
super();
this.state = {
value: null,
}
}
render() {
return (
<button className="square" onClick={this.props.onClick}>
{this.state.value || this.props.value}
</button>
);
}
}
//Board 元件包含了9個squares
class Board extends React.Component {
renderSquare(i) {
return <Square value={this.props.squares[i]}
onClick={() => this.props.onClick(i)} />;
}
render() {
//檢查是否有人獲勝 獲勝無法繼續落子
const winner = calculateWinner(this.props.squares);
let status;
if (winner) {
status = 'Winner:' + winner;
} else {
status = 'Next player: ' + (this.props.xIsNext ? 'X' : 'O');
}
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>
);
}
}
//Game 元件則為我們即將要編寫的程式碼預留了一些位置
class Game extends React.Component {
constructor() {
super();
this.state = {
history: [{
squares: Array(9).fill(null),
}],
xIsNext: true,
stepNumber: 0
}
}
handleClick(i) {
const history = this.state.history;
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = this.state.xIsNext ? 'X' : 'O';
this.setState({
history: history.concat([{
squares: squares
}]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext,
})
}
jumpTo(step) {
this.setState({
stepNumber: step,
xIsNext: (step % 2) ? false : true,
})
}
render() {
const history = this.state.history;
const current = history[this.state.stepNumber];
const winner = calculateWinner(current.squares);
const moves = history.map((step, move) => {
const desc = move ?
'Move #' + move :
'Game start';
return (
<li key={move}>
<a href="#" onClick={() => this.jumpTo(move)} >{desc}</a>
</li>
);
})
let status;
if (winner) {
status = 'Winner: ' + winner;
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
);
}
}
// ========================================
ReactDOM.render(
<Game />,
document.getElementById('root')
);
//判斷遊戲獲勝方的程式碼
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
}