版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第React函數(shù)組件與類的區(qū)別有哪些目錄一、函數(shù)式組件捕獲了渲染所用的值二、閉包讓類組件成為擁有特定props和state的渲染三、區(qū)分useState與useRef的使用首先我們要知道的是,項(xiàng)目性能能主要取決于代碼的作用,而不是選擇函數(shù)式還是類組件。盡管優(yōu)化策略各有略微不同,但它們之間的性能差異可以忽略不計(jì)。
一、函數(shù)式組件捕獲了渲染所用的值
首先我們來(lái)看下面這個(gè)組件:
functionApp(props){
constshowMessage=()={
alert('Hello'+props.user);
consthandleClick=()={
setTimeout(showMessage,3000);
return(
buttonhandleClick}Say/button
}
它渲染了一個(gè)利用來(lái)模擬網(wǎng)絡(luò)請(qǐng)求,然后顯示一個(gè)確認(rèn)警告的按鈕。例如,如果是傳遞進(jìn)來(lái)的props.user是jie,那么三秒后就會(huì)彈出Hellojie。
那么我們用類應(yīng)該怎么寫這個(gè)組件呢?一個(gè)簡(jiǎn)單的重構(gòu)可能就象這樣:
classAppextendsReact.Component{
showMessage=()={
alert('Hello'+ps.user);
handleClick=()={
setTimeout(this.showMessage,3000);
render(){
returnbuttonthis.handleClick}Say/button
}
我們通常做代碼重構(gòu)的時(shí)候都認(rèn)為他們兩個(gè)是等效的,但是事實(shí)真的如此嗎,我們很少注意到它們之間的含義。
下面我們新建一個(gè)react項(xiàng)目,在src下新建兩個(gè)組件,一個(gè)classComponent組件,一個(gè)是functionComponent組件。代碼就是上面我們寫的這兩個(gè)組件,只不過(guò)內(nèi)容稍有區(qū)別:
classComponent:
importReactfrom'react';
classProfilePageextendsReact.Component{
showMessage=()={
alert('你選擇了'+ps.user);
handleClick=()={
setTimeout(this.showMessage,3000);
render(){
returnbuttonthis.handleClick}選擇/button
exportdefaultProfilePage;
functionComponent:
importReactfrom'react';
functionProfilePage(props){
constshowMessage=()={
alert('你選擇了'+props.user);
consthandleClick=()={
setTimeout(showMessage,3000);
return(
buttonhandleClick}選擇/button
exportdefaultProfilePage;
在app.js中我們將這兩個(gè)組件引入:
importReactfrom"react";
importReactDOMfrom"react-dom";
importProfilePageFunctionfrom'./functionComponent';
importProfilePageClassfrom'./classComponent';
exportdefaultclassAppextendsReact.Component{
state={
user:'小杰',
render(){
return(
label
b選擇你想要拜訪的朋友/b
select
value={this.state.user}
onChange={e=this.setState({user:e.target.value})}
optionvalue="小杰"小杰/option
optionvalue="小尚"小尚/option
optionvalue="小寧"小寧/option
/select
/label
h1歡迎來(lái)到{this.state.user}的家!/h1
ProfilePageFunctionuser={this.state.user}/
b(這是來(lái)自函數(shù)式組件的)/b
ProfilePageClassuser={this.state.user}/
b(這是來(lái)自類組件的)/b
}
運(yùn)行項(xiàng)目,科研看到這樣的界面:
當(dāng)我們單擊上面的按鈕時(shí),執(zhí)行的就是函數(shù)式組件,點(diǎn)擊下面的按鈕時(shí),執(zhí)行的就是類。如果按照我們以往的思路,他們二者都會(huì)有相同的結(jié)果,但事實(shí)真的如此嗎?
我們按照下面的順序執(zhí)行:
1.點(diǎn)擊函數(shù)式組件按鈕
2.在點(diǎn)擊后立刻切換想要拜訪的朋友
函數(shù)式組件的執(zhí)行結(jié)果如下:
頁(yè)面彈出的還是我們當(dāng)時(shí)選擇的值
同樣的操作我們?cè)僭囈幌骂惤M件:
現(xiàn)在頁(yè)面彈出的就是我們實(shí)時(shí)更改的值了。
在這個(gè)例子中,第一個(gè)行為是正確的。因?yàn)樽铋_始我選擇要拜訪小杰點(diǎn)擊了確定發(fā)出了命令,然后我再切換到小尚,但是我并沒(méi)有點(diǎn)擊確定,我的組件不應(yīng)該混淆我要拜訪的人。在這里,類組件的實(shí)現(xiàn)很明顯是錯(cuò)誤的。
所以為什么我們的例子中類組件會(huì)有這樣的表現(xiàn)?
讓我們來(lái)仔細(xì)看看我們類組件中的方法:showMessage
showMessage=()={
alert('你選擇了'+ps.user);
};
這個(gè)類方法從中讀取數(shù)據(jù)。在React中Props是不可變的,所以他們永遠(yuǎn)不會(huì)改變。然而,this是,而且永遠(yuǎn)是,可變的。
事實(shí)上,這就是類組件存在的意義。React本身會(huì)隨著時(shí)間的推移而改變,以便你可以在渲染方法以及生命周期方法中得到最新的實(shí)例。所以如果在請(qǐng)求已經(jīng)發(fā)出的情況下我們的組件進(jìn)行了重新渲染,將會(huì)改變。
我們的組件屬于一個(gè)擁有特定props和state的特定渲染。
然而,調(diào)用一個(gè)回調(diào)函數(shù)讀取的timeout會(huì)打斷這種關(guān)聯(lián)。我們的回調(diào)并沒(méi)有與任何一個(gè)特定的渲染綁定在一起,所以它失去了正確的props。
二、閉包讓類組件成為擁有特定props和state的渲染
我們想要以某種方式修復(fù)擁有正確props的渲染與讀取這些props的回調(diào)之間的聯(lián)系。它們?cè)陬惖哪硞€(gè)地方被弄丟了。
一種方法是在調(diào)用事件之前讀取,然后將他們顯式地傳遞到timeout回調(diào)函數(shù)中去:
importReactfrom'react';
classProfilePageextendsReact.Component{
showMessage=(user)={
alert('你選擇了'+user);
handleClick=()={
const{user}=ps;
setTimeout(()=this.showMessage(user),3000);
render(){
returnbuttonthis.handleClick}確定/button
exportdefaultProfilePage;
這種方法會(huì)起作用。然而,這種方法使得代碼明顯變得更加冗長(zhǎng),并且隨著時(shí)間推移容易出錯(cuò)。如果我們需要的不止是一個(gè)props怎么辦?如果我們還需要訪問(wèn)state怎么辦?
然而,如果我們能利用JavaScript閉包的話問(wèn)題將迎刃而解。
通常來(lái)說(shuō)我們會(huì)避免使用閉包,但是在React中,props和state是不可變的,這就消除了閉包的一個(gè)主要缺陷。
這就意味著如果你在一次特定的渲染中捕獲那一次渲染所用的props或者state,你會(huì)發(fā)現(xiàn)他們總是會(huì)保持一致,就如同你的預(yù)期那樣。
classProfilePageextendsReact.Component{
render(){
constprops=ps;
constshowMessage=()={
alert('你選擇了'+props.user);
consthandleClick=()={
setTimeout(showMessage,3000);
returnbuttonhandleClick}確定/button
}
你在渲染的時(shí)候就已經(jīng)捕獲了props。這樣,在它內(nèi)部的任何代碼(包括)都保證可以得到這一次特定渲染所使用的props。上面的例子是正確的,但是看起來(lái)很奇怪。如果你在方法中定義各種函數(shù),而不是使用class的方法,那么使用類的意義在哪里?
所以這個(gè)時(shí)候我們就明白了函數(shù)式組件和類組件的區(qū)別:
functionProfilePage({user}){
constshowMessage=()={
alert('Followed'+user);
consthandleClick=()={
setTimeout(showMessage,3000);
return(
buttonhandleClick}Follow/button
}
當(dāng)父組件使用不同的props來(lái)渲染時(shí),React會(huì)再次調(diào)用函數(shù)。但是我們點(diǎn)擊的事件處理函數(shù),屬于具有自己的值的上一次渲染,并且回調(diào)函數(shù)也能讀取到這個(gè)值。它們都保持完好無(wú)損。
三、區(qū)分useState與useRef的使用
使用Hooks,同樣的原則也適用于狀態(tài)。看這個(gè)例子:
functionMessageThread(){
const[message,setMessage]=useState('');
constshowMessage=()={
alert('Yousaid:'+message);
consthandleSendClick=()={
setTimeout(showMessage,3000);
consthandleMessageChange=(e)={
setMessage(e.target.value);
return(
inputvalue={message}onChange={handleMessageChange}/
buttonhandleSendClick}Send/button
}
如果我發(fā)送一條特定的消息,組件不應(yīng)該對(duì)實(shí)際發(fā)送的是哪條消息感到困惑。這個(gè)函數(shù)組件的變量捕獲了我們?cè)跒g覽器中執(zhí)行單擊處理函數(shù)的那一次渲染。所以當(dāng)我點(diǎn)擊發(fā)送時(shí)那一刻輸入框中的內(nèi)容就會(huì)被設(shè)置為彈出的值。
因此我們知道,在默認(rèn)情況下React中的函數(shù)會(huì)捕獲props和state。但是如果我們想要讀取并不屬于這一次特定渲染的,最新的props和state呢?
在函數(shù)式組件中,你也可以擁有一個(gè)在所有的組件渲染幀中共享的可變變量。它被成為ref:
functionMyComponent(){
constref=useRef(null);
//你可以通過(guò)ref.current來(lái)獲取保存的值.
//...
}
在很多情況下,你并不需要它們,并且分配它們將是一種浪費(fèi)。但是,如果你愿意,你可以這樣手動(dòng)地來(lái)追蹤這些值:
functionMessageThread(){
const[message,setMessage]=useState('');
constlatestMessage=useRef('');
constshowMessage=()={
alert('Yousaid:'+latestMessage.current);
consthandleSendClick=()={
setTimeout(showMessage,3000);
consthandleMessageChange=(e)={
setMessage(e.target.value);
latestMessage.current=e.target.value;
}
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年電力事故應(yīng)急處置知識(shí)競(jìng)賽試題
- 2026年食品安全與健康標(biāo)準(zhǔn)檢測(cè)認(rèn)證試題
- 2026年經(jīng)濟(jì)形勢(shì)分析與市場(chǎng)預(yù)測(cè)模擬題
- 2026年生物醫(yī)學(xué)工程基礎(chǔ)知識(shí)及專業(yè)英語(yǔ)試題
- 2026年酒店管理初級(jí)專業(yè)知識(shí)模擬卷
- 2026年中級(jí)音樂(lè)教師職業(yè)能力測(cè)試題
- 2026年金融行業(yè)1X證書制度考評(píng)員實(shí)務(wù)試題庫(kù)
- 2026年?duì)I銷策略實(shí)戰(zhàn)中級(jí)市場(chǎng)營(yíng)銷經(jīng)理能力測(cè)試題
- 2025年消防設(shè)施操作員初級(jí)技能沖刺題庫(kù)下載
- 2026年汽車維修技師專業(yè)水平考核試題及答案
- 2026重慶高新開發(fā)建設(shè)投資集團(tuán)招聘3人備考考試試題及答案解析
- 老年人管理人員培訓(xùn)制度
- 2026四川成都市錦江區(qū)國(guó)有企業(yè)招聘18人筆試備考試題及答案解析
- 特種工安全崗前培訓(xùn)課件
- 2026屆福建省三明市第一中學(xué)高三上學(xué)期12月月考?xì)v史試題(含答案)
- (正式版)DB51∕T 3342-2025 《爐灶用合成液體燃料經(jīng)營(yíng)管理規(guī)范》
- 2026北京海淀初三上學(xué)期期末語(yǔ)文試卷和答案
- (正式版)HGT 20593-2024 鋼制化工設(shè)備焊接與檢驗(yàn)工程技術(shù)規(guī)范
- 肘關(guān)節(jié)恐怖三聯(lián)征
- 刀模管理制度
- NB-T 47013.2-2015 承壓設(shè)備無(wú)損檢測(cè) 第2部分-射線檢測(cè)
評(píng)論
0/150
提交評(píng)論