堅(jiān)實(shí)的React基礎(chǔ):初學(xué)者指南
在過去的幾個(gè)月里,我一直在使用 React 和 React-Native。我已經(jīng)發(fā)布了兩個(gè)作為產(chǎn)品的應(yīng)用, Kiven Aa(React)和 Pollen Chat(React Native)。當(dāng)我開始學(xué)習(xí) React 時(shí),我找了一些不僅僅是教我如何用 React 寫應(yīng)用的東西(一個(gè)博客,一個(gè)視頻,一個(gè)課程,等等),我也想讓它幫我做好面試準(zhǔn)備。
我發(fā)現(xiàn)的大部分資料都集中在某一單一方面上。所以,這篇文章針對(duì)的是那些希望理論與實(shí)踐***結(jié)合的觀眾。我會(huì)告訴你一些理論,以便你了解幕后發(fā)生的事情,然后我會(huì)向你展示如何編寫一些 React.js 代碼。
如果你更喜歡視頻形式,我在 [YouTube][https://youtu.be/WJ6PgzI16I4] 上傳了整個(gè)課程,請(qǐng)去看看。
讓我們開始……
React.js 是一個(gè)用于構(gòu)建用戶界面的 JavaScript 庫(kù)
你可以構(gòu)建各種單頁(yè)應(yīng)用程序。例如,你希望在用戶界面上實(shí)時(shí)顯示變化的聊天軟件和電子商務(wù)門戶。
一切都是組件
React 應(yīng)用由組件組成,數(shù)量繁多且互相嵌套。你或許會(huì)問:”可什么是組件呢?“
組件是可重用的代碼段,它定義了某些功能在 UI 上的外觀和行為。 比如,按鈕就是一個(gè)組件。
讓我們看看下面的計(jì)算器,當(dāng)你嘗試計(jì)算 2 + 2 = 4 -1 = 3(簡(jiǎn)單的數(shù)學(xué)題)時(shí),你會(huì)在 Google 上看到這個(gè)計(jì)算器。
紅色標(biāo)記表示組件
如上圖所示,這個(gè)計(jì)算器有很多區(qū)域,比如展示窗口和數(shù)字鍵盤。所有這些都可以是許多單獨(dú)的組件或一個(gè)巨大的組件。這取決于在 React 中分解和抽象出事物的程度。你為所有這些組件分別編寫代碼,然后合并這些組件到一個(gè)容器中,而這個(gè)容器又是一個(gè) React 組件。這樣你就可以創(chuàng)建可重用的組件,最終的應(yīng)用將是一組協(xié)同工作的單獨(dú)組件。
以下是一個(gè)你踐行了以上原則并可以用 React 編寫計(jì)算器的方法。
<Calculator>
<DisplayWindow />
<NumPad>
<Key number={1}/>
<Key number={2}/>
.
.
.
<Key number={9}/>
</NumPad>
</Calculator>
沒錯(cuò)!它看起來(lái)像HTML代碼,然而并不是。我們將在后面的部分中詳細(xì)探討它。
設(shè)置我們的 Playground
這篇教程專注于 React 的基礎(chǔ)部分。它沒有偏向 Web 或 React Native(開發(fā)移動(dòng)應(yīng)用)。所以,我們會(huì)用一個(gè)在線編輯器,這樣可以在學(xué)習(xí) React 能做什么之前避免 web 或 native 的具體配置。
我已經(jīng)為讀者在 codepen.io 設(shè)置好了開發(fā)環(huán)境。只需點(diǎn)開該鏈接并且閱讀 HTML 和 JavaScript 中的所有注釋。
控制組件
我們已經(jīng)了解到 React 應(yīng)用是各種組件的集合,結(jié)構(gòu)為嵌套樹。因此,我們需要某種機(jī)制來(lái)將數(shù)據(jù)從一個(gè)組件傳遞到另一個(gè)組件。
進(jìn)入 “props”
我們可以使用 props
對(duì)象將任意數(shù)據(jù)傳遞給我們的組件。 React 中的每個(gè)組件都會(huì)獲取 props
對(duì)象。在學(xué)習(xí)如何使用 props
之前,讓我們學(xué)習(xí)函數(shù)式組件。
a) 函數(shù)式組件
在 React 中,一個(gè)函數(shù)式組件通過 props
對(duì)象使用你傳遞給它的任意數(shù)據(jù)。它返回一個(gè)對(duì)象,該對(duì)象描述了 React 應(yīng)渲染的 UI。函數(shù)式組件也稱為無(wú)狀態(tài)組件。
讓我們編寫***個(gè)函數(shù)式組件。
function Hello(props) {
return <div>{props.name}</div>
}
就這么簡(jiǎn)單。我們只是將 props
作為參數(shù)傳遞給了一個(gè)普通的 JavaScript 函數(shù)并且有返回值。嗯?返回了什么?那個(gè) <div>{props.name}</div>
。它是 JSX(JavaScript Extended)。我們將在后面的部分中詳細(xì)了解它。
上面這個(gè)函數(shù)將在瀏覽器中渲染出以下 HTML。
<!-- If the "props" object is: {name: 'rajat'} -->
<div>
rajat
</div>
閱讀以下有關(guān) JSX 的部分,這一部分解釋了如何從我們的 JSX 代碼中得到這段 HTML 。
如何在 React 應(yīng)用中使用這個(gè)函數(shù)式組件? 很高興你問了! 它就像下面這么簡(jiǎn)單。
<Hello name='rajat' age={26}/>
屬性 name
在上面的代碼中變成了 Hello
組件里的 props.name
,屬性 age
變成了 props.age
。
記住! 你可以將一個(gè) React 組件嵌套在其他 React 組件中。
讓我們?cè)?codepen playground 使用 Hello
組件。用我們的 Hello
組件替換 ReactDOM.render()
中的 div
,并在底部窗口中查看更改。
function Hello(props) {
return <div>{props.name}</div>
}
ReactDOM.render(<Hello name="rajat"/>, document.getElementById('root'));
但是如果你的組件有一些內(nèi)部狀態(tài)怎么辦?例如,像下面的計(jì)數(shù)器組件一樣,它有一個(gè)內(nèi)部計(jì)數(shù)變量,它在
+
和-
鍵按下時(shí)發(fā)生變化。
具有內(nèi)部狀態(tài)的 React 組件
b) 基于類的組件
基于類的組件有一個(gè)額外屬性 state
,你可以用它存放組件的私有數(shù)據(jù)。我們可以用 class
表示法重寫我們的 Hello
。由于這些組件具有狀態(tài),因此這些組件也稱為有狀態(tài)組件。
class Counter extends React.Component {
// this method should be present in your component
render() {
return (
<div>
{this.props.name}
</div>
);
}
}
我們繼承了 React 庫(kù)的 React.Component
類以在 React 中創(chuàng)建基于類的組件。在這里了解更多有關(guān) JavaScript 類的東西。
render()
方法必須存在于你的類中,因?yàn)?React 會(huì)查找此方法,用以了解它應(yīng)在屏幕上渲染的 UI。為了使用這種內(nèi)部狀態(tài),我們首先要在組件
要使用這種內(nèi)部狀態(tài),我們首先必須按以下方式初始化組件類的構(gòu)造函數(shù)中的狀態(tài)對(duì)象。
class Counter extends React.Component {
constructor() {
super();
// define the internal state of the component
this.state = {name: 'rajat'}
}
render() {
return (
<div>
{this.state.name}
</div>
);
}
}
// Usage:
// In your react app: <Counter />
類似地,可以使用 this.props
對(duì)象在我們基于類的組件內(nèi)訪問 props
。
要設(shè)置 state
,請(qǐng)使用 React.Component
的 setState()
。 在本教程的***一部分中,我們將看到一個(gè)這樣的例子。
提示:永遠(yuǎn)不要在
render()
函數(shù)中調(diào)用setState()
,因?yàn)?setState
會(huì)導(dǎo)致組件重新渲染,這將導(dǎo)致***循環(huán)。
基于類的組件具有可選屬性 “state”。
除了 state
以外,基于類的組件有一些聲明周期方法比如 componentWillMount()
。你可以利用這些去做初始化 state
這樣的事, 可是那將超出這篇文章的范疇。
JSX
JSX 是 JavaScript Extended 的縮寫,它是一種編寫 React 組件的方法。使用 JSX,你可以在類 XML 標(biāo)簽中獲得 JavaScript 的全部力量。
你把 JavaScript 表達(dá)式放在 {}
里。下面是一些有效的 JSX 例子。
<button disabled={true}>Press me!</button>
<button disabled={true}>Press me {3+1} times!</button>;
<div className='container'><Hello /></div>
它的工作方式是你編寫 JSX 來(lái)描述你的 UI 應(yīng)該是什么樣子。像 Babel 這樣的轉(zhuǎn)碼器將這些代碼轉(zhuǎn)換為一堆 React.createElement()
調(diào)用。然后,React 庫(kù)使用這些 React.createElement()
調(diào)用來(lái)構(gòu)造 DOM 元素的樹狀結(jié)構(gòu)。對(duì)于 React 的網(wǎng)頁(yè)視圖或 React Native 的 Native 視圖,它將保存在內(nèi)存中。
React 接著會(huì)計(jì)算它如何在展示給用戶的 UI 的內(nèi)存中有效地模仿這個(gè)樹。此過程稱為 reconciliation。完成計(jì)算后,React 會(huì)對(duì)屏幕上的真正 UI 進(jìn)行更改。
React 如何將你的 JSX 轉(zhuǎn)化為描述應(yīng)用 UI 的樹。
你可以使用 Babel 的在線 REPL 查看當(dāng)你寫一些 JSX 的時(shí)候,React 的真正輸出。
使用Babel REPL 轉(zhuǎn)換 JSX 為普通 JavaScript
由于 JSX 只是
React.createElement()
調(diào)用的語(yǔ)法糖,因此可以在沒有 JSX 的情況下使用 React。
現(xiàn)在我們了解了所有的概念,所以我們已經(jīng)準(zhǔn)備好編寫我們之前看到之前的 GIF 圖中的計(jì)數(shù)器組件。
代碼如下,我希望你已經(jīng)知道了如何在我們的 playground 上渲染它。
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = {count: this.props.start || 0}
// the following bindings are necessary to make `this` work in the callback
this.inc = this.inc.bind(this);
this.dec = this.dec.bind(this);
}
inc() {
this.setState({
count: this.state.count + 1
});
}
dec() {
this.setState({
count: this.state.count - 1
});
}
render() {
return (
<div>
<button onClick={this.inc}>+</button>
<button onClick={this.dec}>-</button>
<div>{this.state.count}</div>
</div>
);
}
}
以下是關(guān)于上述代碼的一些重點(diǎn)。
- JSX 使用
駝峰命名
,所以button
的 屬性是onClick
,不是我們?cè)贖TML中用的onclick
。 - 綁定
this
是必要的,以便在回調(diào)時(shí)工作。 請(qǐng)參閱上面代碼中的第8行和第9行。
最終的交互式代碼位于此處。
有了這個(gè),我們已經(jīng)到了 React 速成課程的結(jié)束。我希望我已經(jīng)闡明了 React 如何工作,以及如何使用 React 來(lái)構(gòu)建更大的應(yīng)用程序,使用更小和可重用的組件。