官網(wǎng)代碼:
import React from 'react' import ReactDOM from 'react-dom' import './index.css' function Square(props) { //函數(shù)定義組件,接收一個(gè)單一的“props”對(duì)象并返回了一個(gè)React元素 return ( ); } //如果不需要在 constructor里面使用 props,是可以不用寫(xiě) constructor的 //只有 render 方法的組件:函數(shù)定義組件.只需要簡(jiǎn)單寫(xiě)一個(gè)以props為參數(shù)的function返回JSX元素。愛(ài)掏網(wǎng) - it200.com //其中所有的 this.props 替換成參數(shù) props, //onClick={() => props.onClick()} 直接修改為 onClick={props.onClick} , //注意不能寫(xiě)成 onClick={props.onClick()} //否則 props.onClick 方法會(huì)在 Square 組件渲染時(shí)被直接觸發(fā)而不是等到 Board 組件渲染完成時(shí)通過(guò)點(diǎn)擊觸發(fā) class Board extends React.Component { renderSquare(i) { return (this.props.onClick(i)} /> ); } render() { return ( {this.renderSquare(0)} {this.renderSquare(1)} {this.renderSquare(2)} {this.renderSquare(3)} {this.renderSquare(4)} {this.renderSquare(5)} {this.renderSquare(6)} {this.renderSquare(7)} {this.renderSquare(8)} ); } } class Game extends React.Component { //類定義組件 constructor(props) {//constructor:構(gòu)造方法 this.state 為該組件設(shè)置自身的狀態(tài)數(shù)據(jù) super(props);//子類中調(diào)用父類構(gòu)造函數(shù),子類沒(méi)有自己的this對(duì)象,而是繼承父類的this對(duì)象,如果不調(diào)用super方法,子類就得不到this對(duì)象 this.state = { history: [ { squares: Array(9).fill(null) } ], stepNumber: 0, xIsNext: true //X為先手 }; } handleClick(i) { const history = this.state.history.slice(0, this.state.stepNumber + 1); //返回此刻所有步驟(每走一步向history存入一個(gè)squares數(shù)組) const current = history[history.length - 1];//當(dāng)前的squares數(shù)組 const squares = current.squares.slice();//返回當(dāng)前的squares數(shù)組(相當(dāng)于復(fù)制一個(gè)新的數(shù)組) if (calculateWinner(squares) || squares[i]) { return; } //當(dāng)一方已經(jīng)勝利或是方框里已落子則不可以在此處再落子,否則執(zhí)行下行程序 squares[i] = this.state.xIsNext ? "X" : "O"; this.setState({ history: history.concat([ { squares: squares } ]), //將之前的n個(gè)步驟數(shù)組和此步的步驟數(shù)組連接成為一個(gè)新的二維數(shù)組history, //history里放所有的squares(每走一步出現(xiàn)一個(gè)新的squares),squares里放每個(gè)格子的值 stepNumber: history.length,//一共走了多少步 xIsNext: !this.state.xIsNext //更新squares(步驟)數(shù)組 }); } //slice() 方法會(huì)選取從 start 到數(shù)組結(jié)尾的所有元素。愛(ài)掏網(wǎng) - it200.com //var arr = ['George','John','Thomas','Adrew','Martin']; //document.write(arr.slice(2,4)) //輸出:Thomas,Adrew //[2,4) jumpTo(step) { this.setState({ stepNumber: step, xIsNext: (step % 2) === 0 }); } 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 ? 'Go to move #' + move : 'Go to game start'; return ( ); }); let status; if (winner) { status = "Winner: " + winner; } else { status = "Next player: " + (this.state.xIsNext ? "X" : "O"); } return ( this.handleClick(i)} /> //Board是用戶自定義組件,將JXS屬性(squares:{current.squares})作為單個(gè)對(duì)象(props)傳遞給組件; //-> {current.squares} = props.squares {status}{moves}
); } } // ======================================== ReactDOM.render(, document.getElementById("root")); //此id為root的div中的所有內(nèi)容都將由React DOM來(lái)管理,所以我們將其稱之為“根”DOM 節(jié)點(diǎn) 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 重點(diǎn)學(xué)習(xí)心得:
來(lái)包裹所有組件元素。愛(ài)掏網(wǎng) - it200.com
1.React DOM 首先會(huì)比較元素內(nèi)容先后的不同,而在渲染過(guò)程中只會(huì)更新改變了的部分,將界面視為一個(gè)個(gè)特定時(shí)刻的固定內(nèi)容(就像一幀一幀的動(dòng)畫(huà)),而不是隨時(shí)處于變化之中(而不是處于變化中的一整段動(dòng)畫(huà))。愛(ài)掏網(wǎng) - it200.com
2.組件從概念上看就像是函數(shù),它可以接收任意的輸入值(稱之為“props”),并返回一個(gè)需要在頁(yè)面上展示的React元素。愛(ài)掏網(wǎng) - it200.com
3.組件名稱必須以大寫(xiě)字母開(kāi)頭。愛(ài)掏網(wǎng) - it200.com
4.組件的返回值只能有一個(gè)根元素。愛(ài)掏網(wǎng) - it200.com所以要用一個(gè)
5.所有的React組件必須像純函數(shù)那樣使用它們的props,即不能改變props,純函數(shù):不改變它自己的輸入值。愛(ài)掏網(wǎng) - it200.com純函數(shù): function sum(a, b) { return a + b; } 非純函數(shù): unction withdraw(account, amount) { account.total -= amount; }6.類定義組件和函數(shù)定義組件區(qū)別:
類定義組件允許我們使用其它特性,例如局部狀態(tài)、生命周期鉤子。愛(ài)掏網(wǎng) - it200.com
7.this.props和this.state可能是異步更新,可使用第二種形式的 setState() 來(lái)接受一個(gè)函數(shù)而不是一個(gè)對(duì)象。愛(ài)掏網(wǎng) - it200.com 該函數(shù)將接收先前的狀態(tài)作為第一個(gè)參數(shù),將此次更新被應(yīng)用時(shí)的props做為第二個(gè)參數(shù):this.setState((prevState, props) => ({ counter: prevState.counter + props.increment }));8.狀態(tài)通常被稱為局部或封裝。愛(ài)掏網(wǎng) - it200.com 除了擁有并設(shè)置它的組件外,其它組件不可訪問(wèn)。愛(ài)掏網(wǎng) - it200.com
9.在 React 中另一個(gè)不同是你不能使用返回 false 的方式阻止默認(rèn)行為,你必須明確的使用 preventDefault。愛(ài)掏網(wǎng) - it200.com
10.e 是一個(gè)合成事件,不需要擔(dān)心跨瀏覽器的兼容性問(wèn)題,react封裝了瀏覽器原生事件對(duì)象,并對(duì)瀏覽器做了兼容,和瀏覽器原生事件對(duì)象有相同的接口,如果出于某些原因想使用瀏覽器原生事件,可以使用 nativeEvent 屬性獲取。愛(ài)掏網(wǎng) - it200.com
11.類的方法必須綁定this,必須謹(jǐn)慎對(duì)待 JSX 回調(diào)函數(shù)中的 this,類的方法默認(rèn)是不會(huì)綁定 this 的。愛(ài)掏網(wǎng) - it200.com如果你忘記綁定 this.handleClick 并把它傳入 onClick, 當(dāng)你調(diào)用這個(gè)函數(shù)的時(shí)候 this 的值會(huì)是 undefined。愛(ài)掏網(wǎng) - it200.com通常情況下,如果你沒(méi)有在方法后面添加 () ,例如 onClick={this.handleClick},你應(yīng)該為這個(gè)方法綁定 this。愛(ài)掏網(wǎng) - it200.com
(1)在構(gòu)造函數(shù)中使用bind綁定thisclass Button extends React.Component { constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); } handleClick(){ console.log('this is:', this); } render() { return ( ); } }(2)在調(diào)用的時(shí)候使用bind綁定this
class Button extends React.Component { handleClick(){ console.log('this is:', this); } render() { return ( ); } }(3)在調(diào)用的時(shí)候使用箭頭函數(shù)綁定this
class Button extends React.Component { handleClick(){ console.log('this is:', this); } render() { return ( ); } }(4)使用屬性初始化器語(yǔ)法綁定this(實(shí)驗(yàn)性)
class Button extends React.Component { handleClick=()=>{ console.log('this is:', this); } render() { return ( ); } }比較:
分享到:
方式2和方式3都是在調(diào)用的時(shí)候再綁定this。愛(ài)掏網(wǎng) - it200.com
優(yōu)點(diǎn):寫(xiě)法比較簡(jiǎn)單,當(dāng)組件中沒(méi)有state的時(shí)候就不需要添加類構(gòu)造函數(shù)來(lái)綁定this
缺點(diǎn):每一次調(diào)用的時(shí)候都會(huì)生成一個(gè)新的方法實(shí)例,因此對(duì)性能有影響,并且當(dāng)這個(gè)函數(shù)作為屬性值傳入低階組件的時(shí)候,這些組件可能會(huì)進(jìn)行額外的重新渲染,因?yàn)槊恳淮味际切碌姆椒▽?shí)例作為的新的屬性傳遞。愛(ài)掏網(wǎng) - it200.com
方式1在類構(gòu)造函數(shù)中綁定this,調(diào)用的時(shí)候不需要再綁定
優(yōu)點(diǎn):只會(huì)生成一個(gè)方法實(shí)例,并且綁定一次之后如果多次用到這個(gè)方法也不需要再綁定。愛(ài)掏網(wǎng) - it200.com
缺點(diǎn):即使不用到state,也需要添加類構(gòu)造函數(shù)來(lái)綁定this,代碼量多一點(diǎn)。愛(ài)掏網(wǎng) - it200.com。愛(ài)掏網(wǎng) - it200.com。愛(ài)掏網(wǎng) - it200.com
方式4:利用屬性初始化語(yǔ)法,將方法初始化為箭頭函數(shù),因此在創(chuàng)建函數(shù)的時(shí)候就綁定了this。愛(ài)掏網(wǎng) - it200.com
優(yōu)點(diǎn):創(chuàng)建方法就綁定this,不需要在類構(gòu)造函數(shù)中綁定,調(diào)用的時(shí)候不需要再作綁定。愛(ài)掏網(wǎng) - it200.com結(jié)合了方式1、方式2、方式3的優(yōu)點(diǎn)
缺點(diǎn):目前仍然是實(shí)驗(yàn)性語(yǔ)法,需要用babel轉(zhuǎn)譯。愛(ài)掏網(wǎng) - it200.com
總結(jié):
方式1是官方推薦的綁定方式,也是性能最好的方式。愛(ài)掏網(wǎng) - it200.com方式2和方式3會(huì)有性能影響并且當(dāng)方法作為屬性傳遞給子組件的時(shí)候會(huì)引起重渲問(wèn)題。愛(ài)掏網(wǎng) - it200.com方式4目前屬于實(shí)驗(yàn)性語(yǔ)法,但是是最好的綁定方式,需要結(jié)合bable轉(zhuǎn)譯。愛(ài)掏網(wǎng) - it200.com
- 上一篇:導(dǎo)出文件(記錄一下)
- 下一篇:原生 JS 實(shí)現(xiàn)移動(dòng)端 Touch 滑動(dòng)反彈