溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

學(xué)習(xí) React.js 比你想象的要簡單

發(fā)布時(shí)間:2020-07-11 13:03:40 來源:網(wǎng)絡(luò) 閱讀:424 作者:可樂程序員 欄目:web開發(fā)

通過 Medium 中的一篇文章來學(xué)習(xí) React.js 的基本原理

學(xué)習(xí) React.js 比你想象的要簡單


你有沒有注意到在 React 的 logo 中隱藏著一個(gè)六角星?只是順便提下...

去年我寫了一本簡短的關(guān)于學(xué)習(xí) React.js 的書,有 100 頁左右。今年,我要挑戰(zhàn)自己 —— 將其總結(jié)成一篇文章,并向 Medium 投稿。

這篇文章不是講什么是 React 或者 你該怎樣學(xué)習(xí) React。這是在面向那些已經(jīng)熟悉了 JavaScript 和 DOM API 的人的 React.js 基本原理介紹

本文采用嵌入式 jsComplete 代碼段,所以為了方便閱讀,你需要一個(gè)合適的屏幕寬度。

下面所有的代碼都僅供參考。它們也純粹是為了表達(dá)概念而提供的例子。它們中的大多數(shù)有更好的實(shí)踐方式。

您可以編輯和執(zhí)行下面的任何代碼段。使用?Ctrl+Enter?執(zhí)行代碼。每一段的右下角有一個(gè)點(diǎn)擊后可以在 jsComplete/repl 進(jìn)行全屏模式編輯或運(yùn)行代碼的鏈接。


1 React 全部都是組件化的

React 是圍繞可重用組件的概念設(shè)計(jì)的。你定義小組件并將它們組合在一起形成更大的組件。

無論大小,所有組件都是可重用的,甚至在不同的項(xiàng)目中也是如此。

React 組件最簡單的形式,就是一個(gè)普通的 JavaScript 函數(shù):

function?Button?(props)?{?//?這里返回一個(gè)?DOM?元素,例如:
?return?<button?type="submit">{props.label}</button>;
}//?將按鈕組件呈現(xiàn)給瀏覽器ReactDOM.render(<Button?label="Save"?/>,?mountNode)復(fù)制代碼

例 1:編輯上面的代碼并按 Ctrl+Enter 鍵執(zhí)行(譯者注:譯文暫時(shí)沒有這個(gè)功能,請?jiān)L問原文使用此功能,下同)

括號(hào)中的 button 標(biāo)簽將稍后解釋?,F(xiàn)在不要擔(dān)心它們。ReactDOM 也將稍后解釋,但如果你想測試這個(gè)例子和所有接下來的例子,上述 render 函數(shù)是必須的。(React 將要接管和控制的是 ReactDOM.render 的第 2 個(gè)參數(shù)即目標(biāo) DOM 元素)。在 jsComplete REPL 中,你可以使用特殊的變量 mountNode。

例 1 的注意事項(xiàng):

  • 組件名稱首字母大寫,Button。必須要這樣做是因?yàn)槲覀儗⑻幚?HTML 元素和 React 元素的混合。小寫名稱是為 HTML 元素保留的。事實(shí)上,將 React 組件命名為 “button” 然后你就會(huì)發(fā)現(xiàn) ReactDOM 會(huì)忽略這個(gè)函數(shù),僅僅是將其作為一個(gè)普通的空 HTML 按鈕來渲染。

  • 每個(gè)組件都接收一個(gè)屬性列表,就像 HTML 元素一樣。在 React 中,這個(gè)列表被稱為屬性。雖然你可以將一個(gè)函數(shù)隨意命名。

  • 在上面 Button 函數(shù)組件的返回輸出中,我們奇怪地寫了段看上去像 HTML 的代碼。這實(shí)際上既不是 JavaScript 也不是 HTML,老實(shí)說,這甚至不是 React.js。然而它非常流行,以至于成為 React 應(yīng)用程序中的默認(rèn)值。這就是所謂的 JSX,這是一個(gè)JavaScript 的擴(kuò)展。JSX 也是一個(gè)折中方案!繼續(xù)嘗試并在上面的函數(shù)中返回其他 HTML 元素,看看它們是如何被支持的(例如,返回一個(gè)文本輸入元素)。

2 JSX 輸出的是什么?

上面的例 1 可以用沒有 JSX 的純 React.js 編寫,如下:

function?Button?(props)?{
?return?React.createElement(?"button",
?{?type:?"submit"?},
?props.label
?);
}//?要使用?Button,你可以這么做ReactDOM.render(
?React.createElement(Button,?{?label:?"Save"?}),
?mountNode
);復(fù)制代碼

例 2:不使用 JSX 編寫 React 組件

在 React 頂級 API 中,createElement 函數(shù)是主函數(shù)。這是你需要學(xué)習(xí)的 7 個(gè) API 中的 1 個(gè)。React 的 API 就是這么小。

就像 DOM 自身有一個(gè) document.createElement 函數(shù)來創(chuàng)建一個(gè)由標(biāo)簽名指定的元素一樣,React 的 createElement 函數(shù)是一個(gè)高級函數(shù),有和 document.createElement 同樣的功能,但它也可以用于創(chuàng)建一個(gè)表示 React 組件的元素。當(dāng)我們使用上面例 2 中的按鈕組件時(shí),我們使用的是后者。

不像 document.createElement,React 的 createElement 在接收第二個(gè)參數(shù)后,接收一個(gè)動(dòng)態(tài)參數(shù),它表示所創(chuàng)建元素的子元素。所以 createElement 實(shí)際上創(chuàng)建了一個(gè)

這里就是這樣的一個(gè)例子:

const?InputForm?=?React.createElement(?"form",
?{?target:?"_blank",?action:?"https://google.com/search"?},
?React.createElement("div",?null,?"Enter?input?and?click?Search"),
?React.createElement("input",?{?className:?"big-input"?}),
?React.createElement(Button,?{?label:?"Search"?})
);//?InputForm?使用?Button?組件,所以我們需要這樣做:function?Button?(props)?{?return?React.createElement(?"button",
?{?type:?"submit"?},
?props.label
?);
}//?然后我們可以通過?.render?方法直接使用?InputFormReactDOM.render(InputForm,?mountNode);復(fù)制代碼

例 3:React 創(chuàng)建元素的 API

上面例子中的一些事情值得注意:

  • InputForm 不是一個(gè) React 組件;它僅僅是一個(gè) React?元素。這就是為什么我們可以在 ReactDOM.render 中直接使用它并且可以在調(diào)用時(shí)不使用 <InputForm /> 的原因。

  • React.createElement 函數(shù)在前兩個(gè)參數(shù)后接收了多個(gè)參數(shù)。從第3個(gè)參數(shù)開始的參數(shù)列表構(gòu)成了創(chuàng)建元素的子項(xiàng)列表。

  • 我們可以嵌套 React.createElement 調(diào)用,因?yàn)樗?JavaScript。

  • 當(dāng)這個(gè)元素不需要屬性時(shí),React.createElement 的第二個(gè)參數(shù)可以為空或者是一個(gè)空對象。

  • 我們可以在 React 組件中混合 HTML 元素。你可以將 HTML 元素作為內(nèi)置的 React 組件。

  • React 的 API 試圖和 DOM API 一樣,這就是為什么我們在 input 元素中使用 className 代替 class 的原因。我們都希望如果 React 的 API 成為 DOM API 本身的一部分,因?yàn)?,你知道,它要好得多?/p>

上述的代碼是當(dāng)你引入 React 庫的時(shí)候?yàn)g覽器是怎樣理解的。瀏覽器不會(huì)處理任何 JSX 業(yè)務(wù)。然而,我們更喜歡看到和使用 HTML,而不是那些 createElement 調(diào)用(想象一下只使用 document.createElement 構(gòu)建一個(gè)網(wǎng)站?。?。這就是 JSX 存在的原因。取代上述調(diào)用 React.createElement 的方式,我們可以使用一個(gè)非常簡單類似于 HTML 的語法:

const?InputForm?=
?<form?target="_blank"?action="https://google.com/search">
?<div>Enter?input?and?click?Search</div>
?<input?className="big-input"?name="q"?/>
?<Button?label="Search"?/>
?</form>;//?InputForm?“仍然”使用?Button?組件,所以我們也需要這樣。//?JXS?或者普通的表單都會(huì)這樣做function?Button?(props)?{?//?這里返回一個(gè)?DOM?元素。例如:
?return?<button?type="submit">{props.label}</button>;
}//?然后我們可以直接通過?.render?使用?InputFormReactDOM.render(InputForm,?mountNode);復(fù)制代碼

例 4:為什么在 React 中 JSX 受歡迎(和例 3 相比)

注意上面的幾件事:

  • 這不是 HTML 代碼。比如,我們?nèi)匀豢梢允褂?className 代替 class。

  • 我們?nèi)栽诳紤]怎樣讓上述的 JavaScript 看起來像是 HTML??匆幌挛以谧詈笫窃鯓犹砑拥?。

我們在上面(例 4)中寫的就是 JSX。然而,我們要將編譯后的版本(例 3)給瀏覽器。要做到這一點(diǎn),我們需要使用一個(gè)預(yù)處理器將 JSX 版本轉(zhuǎn)換為 React.createElement 版本。

這就是 JSX。這是一種折中的方案,允許我們用類似 HTML 的語法來編寫我們的 React 組件,這是一個(gè)很好的方法。

“Flux” 在頭部作為韻腳來使用,但它也是一個(gè)非常受歡迎的 應(yīng)用架構(gòu),由 Facebook 推廣。最出名的是 Redux,F(xiàn)lux 和 React 非常合適。

JSX,可以單獨(dú)使用,不僅僅適用于 React。

3 你可以在 JavaScript 的任何地方使用 JSX

在 JSX 中,你可以在一對花括號(hào)內(nèi)使用任何 JavaScript 表達(dá)式。

const?RandomValue?=?()?=>?<div>
?{?Math.floor(Math.random()?*?100)?}
?</div>;
//?使用:
ReactDOM.render(<RandomValue?/>,?mountNode);復(fù)制代碼

例 5:在 JSX 中使用 JavaScript 表達(dá)式

任何 JavaScript 表達(dá)式可以直接放在花括號(hào)中。這相當(dāng)于在 JavaScript 中插入 ${} 模板。

這是 JSX 內(nèi)唯一的約束:只有表達(dá)式。例如,你不能使用 if 語句,但三元表達(dá)式是可以的。

JavaScript 變量也是表達(dá)式,所以當(dāng)組件接受屬性列表時(shí)(不包括 RandomValue 組件,props 是可選擇的),你可以在花括號(hào)里使用這些屬性。我們在上述(例 1)的 Button 組件是這樣使用的。

JavaScript 對象也是表達(dá)式。有些時(shí)候我們在花括號(hào)中使用 JavaScript 對象,這看起來像是使用了兩個(gè)花括號(hào),但是在花括號(hào)中確實(shí)只有一個(gè)對象。其中一個(gè)用例就是將 CSS 樣式對象傳遞給響應(yīng)中的特殊樣式屬性:

const?ErrorDisplay?=?({message})?=>?<div?style={?{?color:?'red',?backgroundColor:?'yellow'?}?}>?{message}
?</div>;
//?使用
ReactDOM.render(?<ErrorDisplay
?message="These?aren't?the?droids?you're?looking?for"
?/>,
?mountNode
);復(fù)制代碼

例 6:一個(gè)對象傳遞特殊的 React 樣式參數(shù)

注意我解構(gòu)的只是在屬性參數(shù)之外的信息。這只是 JavaScript。還要注意上面的樣式屬性是一個(gè)特殊的屬性(同樣,它不是 HTML,它更接近 DOM API)。我們使用一個(gè)對象作為樣式屬性的值并且這個(gè)對象定義樣式就像我們使用 JavaScript 那樣(我們可以這樣做)。

你可以在 JSX 中使用 React 元素。因?yàn)檫@也是一個(gè)表達(dá)式(記住,一個(gè) React 元素只是一個(gè)函數(shù)調(diào)用):

const?MaybeError?=?({errorMessage})?=>?<div>
?{errorMessage?&&?<ErrorDisplay?message={errorMessage}?/>}?</div>;
//?MaybeError?組件使用?ErrorDisplay?組件
const?ErrorDisplay?=?({message})?=>?<div?style={?{?color:?'red',?backgroundColor:?'yellow'?}?}>?{message}
?</div>;
//?現(xiàn)在我們使用?MaybeError?組件:
ReactDOM.render(?<MaybeError
?errorMessage={Math.random()?>?0.5???'Not?good'?:?''}
?/>,
?mountNode
);復(fù)制代碼

例 7:一個(gè) React 元素是一個(gè)可以通過 {} 使用的表達(dá)式

上述 MaybeError 組件只會(huì)在有 errorMessage 傳入或者另外有一個(gè)空的 div 才會(huì)顯示 ErrorDisplay 組件。React 認(rèn)為 {true}、 {false}

{undefined} 和 {null} 是有效元素,不呈現(xiàn)任何內(nèi)容。

我們也可以在 JSX 中使用所有的 JavaScript 的集合方法(map、reduce 、filter、 concat 等)。因?yàn)樗麄兎祷氐囊彩潜磉_(dá)式:

const?Doubler?=?({value=[1,?2,?3]})?=>?<div>
?{value.map(e?=>?e?*?2)}
?</div>;
//?使用下面內(nèi)容?
ReactDOM.render(<Doubler?/>,?mountNode);復(fù)制代碼

例 8:在 {} 中使用數(shù)組

請注意我是如何給出上述 value 屬性的默認(rèn)值的,因?yàn)檫@全部都只是 JavaScript。注意我只是在 div 中輸出一個(gè)數(shù)組表達(dá)式。React 是完全可以的。它只會(huì)在文本節(jié)點(diǎn)中放置每一個(gè)加倍的值。

4 你可以使用 JavaScript 類寫 React 組件

簡單的函數(shù)組件非常適合簡單的需求,但是有的時(shí)候我們需要的更多。React 也支持通過使用 JavaScript 類來創(chuàng)建組件。這里 Button 組件(在例 1 中)就是使用類的語法編寫的。

class?Button?extends?React.Component?{
?render()?{?return?<button>{this.props.label}</button>;
?}
}//?使用(相同的語法)ReactDOM.render(<Button?label="Save"?/>,?mountNode);復(fù)制代碼

例 9:使用 JavaScript 類創(chuàng)建組件

類的語法是非常簡單的:定義一個(gè)擴(kuò)展的 React.Component 類(另一個(gè)你需要學(xué)習(xí)的 React 的頂級 API)。該類定義了一個(gè)單一的實(shí)例函數(shù) —— render(),并使函數(shù)返回虛擬 DOM 對象。每一次我們使用基于類的 Button 組件(例如,通過 <Button ... />),React 將從這個(gè)基于類的組件中實(shí)例化對象,并在 DOM 樹中使用該對象。

這就是為什么上面的例子中我們可以在 JSX 中使用 this.props.label 渲染輸出的原因,因?yàn)槊恳粋€(gè)組件都有一個(gè)特殊的稱為 props 的?實(shí)例?屬性,這讓所有的值傳遞給該組件時(shí)被實(shí)例化。

由于我們有一個(gè)與組件的單個(gè)使用相關(guān)聯(lián)的實(shí)例,所以我們可以按照自己的意愿定制該實(shí)例。例如,我們可以通過使用常規(guī) JavaScript 構(gòu)造函數(shù)來構(gòu)造它:

class?Button?extends?React.Component?{
?constructor(props)?{?super(props);?this.id?=?Date.now();
?}
?render()?{?return?<button?id={this.id}>{this.props.label}</button>;
?}
}//?使用ReactDOM.render(<Button?label="Save"?/>,?mountNode);復(fù)制代碼

例 10:自定義組件實(shí)例

我們也可以定義類的原型并且在任何我們希望的地方使用,包括在返回的 JSX 輸出的內(nèi)部:

class?Button?extends?React.Component?{
?clickCounter?=?0;
?handleClick?=?()?=>?{
?console.log(`Clicked:?${++this.clickCounter}`);
?};
?render()?{?return?(
?<button?id={this.id}?onClick={this.handleClick}>
?{this.props.label}
?</button>
?);
?}
}//?使用ReactDOM.render(<Button?label="Save"?/>,?mountNode);復(fù)制代碼

例 11:使用類的屬性(通過單擊保存按鈕進(jìn)行測試)

注意上述例 11 中的幾件事情

  • handleClick 函數(shù)使用 JavaScript 新提出的 class-field syntax 語法。這仍然是 stage-2,但是這是訪問組件安裝實(shí)例(感謝箭頭函數(shù))最好的選擇(因?yàn)楹芏嘣颍?。然而,你需要使用類?Babel 的編譯器解碼為 stage-2(或者僅僅是類字段語法)來讓上述代碼工作。 jsComplete REPL 有預(yù)編譯功能。

//?錯(cuò)誤:onClick={this.handleClick()}//?正確:onClick={this.handleClick}復(fù)制代碼

5 React 中的事件:兩個(gè)重要的區(qū)別

當(dāng)處理 React 元素中的事件時(shí),我們與 DOM API 的處理方式有兩個(gè)非常重要的區(qū)別:

  • 所有 React 元素屬性(包括事件)都使用?camelCase?命名,而不是?lowercase。例如是 onClick 而不是 onclick。

  • 我們將實(shí)際的 JavaScript 函數(shù)引用傳遞給事件處理程序,而不是字符串。例如是 onClick={handleClick} 而不是 onClick="handleClick"。

React 用自己的對象包裝 DOM 對象事件以優(yōu)化事件處理的性能,但是在事件處理程序內(nèi)部,我們?nèi)匀豢梢栽L問 DOM 對象上所有可以訪問的方法。React 將經(jīng)過包裝的事件對象傳遞給每個(gè)調(diào)用函數(shù)。例如,為了防止表單提交默認(rèn)提交操作,你可以這樣做:

class?Form?extends?React.Component?{
?handleSubmit?=?(event)?=>?{
?event.preventDefault();
?console.log('Form?submitted');
?};
?render()?{?return?(
?<form?onSubmit={this.handleSubmit}>
?<button?type="submit">Submit</button>
?</form>
?);
?}
}//?使用ReactDOM.render(<Form?/>,?mountNode);復(fù)制代碼

例 12:使用包裝過的對象

6 每一個(gè) React 組件都有一個(gè)故事:第 1 部分

以下僅適用于類組件(擴(kuò)展 React.Component)。函數(shù)組件有一個(gè)稍微不同的故事。

  1. 首先,我們定義了一個(gè)模板來創(chuàng)建組件中的元素。

  2. 然后,我們在某處使用 React。例如,在 render 內(nèi)部調(diào)用其他的組件,或者直接使用 ReactDOM.render。

  3. 然后,React 實(shí)例化一個(gè)對象然后給它設(shè)置?props?然后我們可以通過 this.props 訪問。這些屬性都是我們在第 2 步傳入的。

  4. 因?yàn)檫@些全部都是 JavaScript,constructor 方法將會(huì)被調(diào)用(如果定義的話)。這是我們稱之為的第一個(gè):組件生命周期方法。

  5. 接下來 React 計(jì)算渲染之后的輸出方法(虛擬 DOM 節(jié)點(diǎn))。

  6. 因?yàn)檫@是 React 第一次渲染元素,React 將會(huì)與瀏覽器連通(代表我們使用 DOM API)來顯示元素。這整個(gè)過程稱為?mounting

  7. 接下來 React 調(diào)用另一個(gè)生命周期函數(shù),稱為 componentDidMount。我們可以這樣使用這個(gè)方法,例如:在 DOM 上做一些我們現(xiàn)在知道的在瀏覽器中存在的東西。在此生命周期方法之前,我們使用的 DOM 都是虛擬的。

  8. 一些組件的故事到此結(jié)束,其他組件得到卸載瀏覽器 DOM 中的各種原因。在后一種情況發(fā)生時(shí),會(huì)調(diào)用另一個(gè)生命周期的方法,componentWillUnmount。

  9. 任何 mounted 的元素的狀態(tài)都可能會(huì)改變。該元素的父級可能會(huì)重新渲染。無論哪種情況,mounted 的元素都可能接收到不同的屬性集。React 的魔力就是這兒,我們實(shí)際上需要的正是 React 的這一點(diǎn)!在這一點(diǎn)之前,說實(shí)話,我們并不需要 React。

  10. 組價(jià)的故事還在繼續(xù),但是在此之前,我們需要理解我所說的這種狀態(tài)

7 React 組件可以具有私有狀態(tài)

以下只適用于類組件。我有沒有提到有人叫表象而已的部件?dumb?

狀態(tài)類是任何 React 類組件中的一個(gè)特殊字段。React 檢測每一個(gè)組件狀態(tài)的變化,但是為了 React 更加有效,我們必須通過 React 的另一個(gè) API 改變狀態(tài)字段,這就是我們要學(xué)習(xí)的另一個(gè) API —— this.setState:

class?CounterButton?extends?React.Component?{
?state?=?{?clickCounter:?0,?currentTimestamp:?new?Date(),
?};
?handleClick?=?()?=>?{?this.setState((prevState)?=>?{?return?{?clickCounter:?prevState.clickCounter?+?1?};
?});
?};
?componentDidMount()?{
?setInterval(()?=>?{?this.setState({?currentTimestamp:?new?Date()?})
?},?1000);
?}
?render()?{?return?(?<div>
?<button?onClick={this.handleClick}>Click</button>
?<p>Clicked:?{this.state.clickCounter}</p>
?<p>Time:?{this.state.currentTimestamp.toLocaleString()}</p>
?</div>
?);
?}
}//?使用ReactDOM.render(<CounterButton?/>,?mountNode);復(fù)制代碼

例 13:setState 的 API

這可能是最重要的一個(gè)例子因?yàn)檫@將是你完全理解 React 基礎(chǔ)知識(shí)的方式。這個(gè)例子之后,還有一些小事情需要學(xué)習(xí),但從那時(shí)起主要是你和你的 JavaScript 技能。

讓我們來看一下例 13,從類開始,總共有兩個(gè),一個(gè)是一個(gè)初始化的有初始值為 0 的 clickCounter 對象和一個(gè)從 new Date() 開始的 currentTimestamp。

另一個(gè)類是 handleClick 函數(shù),在渲染方法中我們給按鈕元素傳入 onClick 事件。通過使用 setState 的 handleClick 方法修改了組件的實(shí)例狀態(tài)。要注意到這一點(diǎn)。

另一個(gè)我們修改狀態(tài)的地方是在一個(gè)內(nèi)部的定時(shí)器,開始在內(nèi)部的 componentDidMount 生命周期方法。它每秒鐘調(diào)用一次并且執(zhí)行另一個(gè)函數(shù)調(diào)用 this.setState。

在渲染方法中,我們使用具有正常讀語法的狀態(tài)上的兩個(gè)屬性(沒有專門的 API)。

現(xiàn)在,注意我們更新狀態(tài)使用兩種不同的方式:

  1. 通過傳入一個(gè)函數(shù)然后返回一個(gè)對象。我們在 handleClick 函數(shù)內(nèi)部這樣做。

  2. 通過傳入一個(gè)正則對象,我們在在區(qū)間回調(diào)中這樣做。

這兩種方式都是可以接受的,但是當(dāng)你同時(shí)讀寫狀態(tài)時(shí),第一種方法是首選的(我們這樣做)。在區(qū)間回調(diào)中,我們只向狀態(tài)寫入而不讀它。當(dāng)有問題時(shí),總是使用第一個(gè)函數(shù)作為參數(shù)語法。伴隨著競爭條件這更安全,因?yàn)?setstate 實(shí)際上是一個(gè)異步方法。

我們應(yīng)該怎樣更新狀態(tài)呢?我們返回一個(gè)有我們想要更新的的值的對象。注意,在調(diào)用 setState 時(shí),我們?nèi)慷紡臓顟B(tài)中傳入一個(gè)屬性或者全都不。這完全是可以的因?yàn)?setState 實(shí)際上?合并?了你通過它(返回值的函數(shù)參數(shù))與現(xiàn)有的狀態(tài),所以,沒有指定一個(gè)屬性在調(diào)用 setState 時(shí)意味著我們不希望改變屬性(但不刪除它)。

學(xué)習(xí) React.js 比你想象的要簡單


8 React 將要反應(yīng)

React 的名字是從狀態(tài)改變的反應(yīng)中得來的(雖然沒有反應(yīng),但也是在一個(gè)時(shí)間表中)。這里有一個(gè)笑話,React 應(yīng)該被命名為Schedule!

然而,當(dāng)任何組件的狀態(tài)被更新時(shí),我們用肉眼觀察到的是對該更新的反應(yīng),并自動(dòng)反映了瀏覽器 DOM 中的更新(如果需要的話)。

將渲染函數(shù)的輸入視為兩種:

  • 通過父元素傳入的屬性

  • 以及可以隨時(shí)更新的內(nèi)部私有狀態(tài)

當(dāng)渲染函數(shù)的輸入改變時(shí),輸出可能也會(huì)改變。

React 保存了渲染的歷史記錄,當(dāng)它看到一個(gè)渲染與前一個(gè)不同時(shí),它將計(jì)算它們之間的差異,并將其有效地轉(zhuǎn)換為在 DOM 中執(zhí)行的實(shí)際 DOM 操作。

9 React 是你的代碼

您可以將 React 看作是我們用來與瀏覽器通信的代理。以上面的當(dāng)前時(shí)間戳顯示為例。取代每一秒我們都需要手動(dòng)去瀏覽器調(diào)用 DOM API 操作來查找和更新 p#timestamp 元素,我們僅僅改變組件的狀態(tài)屬性,React 做的工作代表我們與瀏覽器的通信。我相信這就是為什么 React 這么受歡迎的真正原因;我們只是不喜歡和瀏覽器先生談話(以及它所說的 DOM 語言的很多方言),并且 React 自愿傳遞給我們,免費(fèi)的!

10 每一個(gè) React 組件都有一個(gè)故事:第 2 部分

現(xiàn)在我們知道了一個(gè)組件的狀態(tài),當(dāng)該狀態(tài)發(fā)生變化的時(shí)候,我們來了解一下關(guān)于這個(gè)過程的最后幾個(gè)概念。

  1. 當(dāng)組件的狀態(tài)被更新時(shí),或者它的父進(jìn)程決定更改它傳遞給組件的屬性時(shí),組件可能需要重新渲染。

  2. 如果后者發(fā)生,React 會(huì)調(diào)用另一個(gè)生命周期方法:componentWillReceiveProps。

  3. 如果狀態(tài)對象或傳遞的屬性改變了,React 有一個(gè)重要的決定要做:組件是否應(yīng)該在 DOM 中更新?這就是為什么它調(diào)用另一個(gè)重要的生命周期方法 shouldComponentUpdate 的原因 。此方法是一個(gè)實(shí)際問題,因此,如果需要自行定制或優(yōu)化渲染過程,則必須通過返回 true 或 false 來回答這個(gè)問題。

  4. 如果沒有自定義 shouldComponentUpdate,React 的默認(rèn)事件在大多數(shù)情況下都能處理的很好。

  5. 首先,這個(gè)時(shí)候會(huì)調(diào)用另一生命周期的方法:componentWillUpdate。然后,React 將計(jì)算新渲染過的輸出,并將其與最后渲染的輸出進(jìn)行對比。

  6. 如果渲染過的輸出和之前的相同,React 不進(jìn)行處理(不需要和瀏覽器先生對話)。

  7. 如果有不同的地方,React 將不同傳達(dá)給瀏覽器,像我們之前看到的那樣。

  8. 在任何情況下,一旦一個(gè)更新程序發(fā)生了,無論以何種方式(即使有相同的輸出),React 會(huì)調(diào)用最后的生命周期方法:componentDidUpdate。

生命周期方法是逃生艙口。如果你沒有做什么特別的事情,你可以在沒有它們的情況下創(chuàng)建完整的應(yīng)用程序。它們非常方便地分析應(yīng)用程序中正在發(fā)生的事情,并進(jìn)一步優(yōu)化 React 更新的性能。

感謝閱讀。如果您覺得這篇文章有幫助,請點(diǎn)擊下面的 。請關(guān)注我的更多關(guān)于 React.js 和 JavaScript 的文章。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI