成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

【譯】函數(shù)組件和類(lèi)組件有什么不同?

gself / 2578人閱讀

摘要:但是,你可能已經(jīng)注意到,當(dāng)你試圖通過(guò)指定依賴(lài)數(shù)組來(lái)優(yōu)化時(shí),可能會(huì)遇到帶有過(guò)時(shí)閉包的錯(cuò)誤。這是否意味著閉包是問(wèn)題所在我不這么認(rèn)為。到目前為止,我所看到的所有情況下,過(guò)時(shí)的閉包問(wèn)題都是由于錯(cuò)誤地假設(shè)函數(shù)不更改或總是相同而發(fā)生的。

原文鏈接:https://overreacted.io/how-ar...

在很長(zhǎng)一段時(shí)間內(nèi),標(biāo)準(zhǔn)答案是class components提供更多的特性(像state)。但隨著Hooks的出現(xiàn),答案就不再是這樣子了。

或許你聽(tīng)說(shuō)過(guò)他們中的一個(gè)性能可能更好,哪一個(gè)?因?yàn)楦鞣N的判斷標(biāo)準(zhǔn)獲取都存在缺陷,所以我們需要小心仔細(xì)的得出結(jié)論。性能的好壞主要取決于什么?它主要取決于你的代碼在做什么,而不是你使用的是function還是class。在我們的觀察中,盡管優(yōu)化的策略可能會(huì)有些許的不同,但性能的差異幾乎可以忽略不及。

無(wú)論是哪種情況,我們都不建議你重寫(xiě)現(xiàn)有的組件,除非你有一些其他的原因或者是想成為Hooks的早期的采用者。Hooks仍然是一個(gè)新特性(就像2014年的React一樣),一些最佳實(shí)踐還沒(méi)有被寫(xiě)入到教程中。

那我們?cè)撛趺崔k?function componentsclass components之間有什么本質(zhì)的區(qū)別嗎?顯然,在構(gòu)思模型中是不同的。在這篇文章中,我們將看到他們之間最大的區(qū)別,自從2015年推出function componetns以來(lái),它就一直存在著,但是卻經(jīng)常被忽視:

function components捕獲渲染值(capture value)

注意: 本文并不是對(duì)函數(shù)或者類(lèi)的值做判斷。我只描述了React中這兩個(gè)編程模型之間的區(qū)別。有關(guān)更廣泛地采用函數(shù)的問(wèn)題,請(qǐng)參閱hooks常見(jiàn)問(wèn)題解答。

思考下面這樣一個(gè)組件:

function ProfilePage(props) {
  const showMessage = () => {
    alert("Followed " + props.user);
  };

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };

  return (
    
  );
}

這個(gè)組件通過(guò)setTimeout模擬網(wǎng)絡(luò)請(qǐng)求,在點(diǎn)擊按鈕3秒后彈出props.user的值,如果props.user的值是Dan的話(huà),他將在點(diǎn)擊后3秒彈出“Followed Dan”。(注意,使用箭頭函數(shù)還是函數(shù)聲明的形式并不重要,handleClick函數(shù)的工作方式完全相同)

如果改寫(xiě)成class形式可能長(zhǎng)下面這個(gè)樣子:

class ProfilePage extends React.Component {
  showMessage = () => {
    alert("Followed " + this.props.user);
  };

  handleClick = () => {
    setTimeout(this.showMessage, 3000);
  };

  render() {
    return ;
  }
}

通常認(rèn)為這兩段代碼是等效的。但是大家經(jīng)常在這兩種形式之間來(lái)回切換代碼而不去關(guān)注他們的含義。

然而其實(shí)這兩段代碼是有細(xì)微的差別的,就我個(gè)人而言,我花費(fèi)了一段時(shí)間才看出來(lái)。

如果你自己想弄清楚的話(huà),這里有一個(gè)在線(xiàn)demo。本文的剩余部分解釋了有什么不同和它的重要性。

再繼續(xù)之前,我要強(qiáng)調(diào),我所描述的差異本身和React Hooks無(wú)關(guān),上面的例子甚至都沒(méi)有使用Hooks。

這全部都是React中,function和class的差別。如果你想要在React應(yīng)用中去頻繁的使用function components,那么你應(yīng)該去了結(jié)它。

我們將用一個(gè)在React應(yīng)用程序中常見(jiàn)的錯(cuò)誤來(lái)說(shuō)明這一區(qū)別。

打開(kāi)這個(gè)示例,有一個(gè)主頁(yè)select和兩個(gè)主頁(yè),且每一個(gè)包含一個(gè)Follow按鈕。

嘗試按照下面的順序操作:

點(diǎn)擊一個(gè)Follow按鈕

改變select選項(xiàng)然后等待3秒

查看alert的文字

你會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題:

function components中,在Dan的主頁(yè)點(diǎn)擊follow然后切換到Sophie,alert仍然會(huì)展示“Followed Dan”。

class components中,alert的卻是“Followed Sophie”。

在這個(gè)例子中,第一個(gè)行為是正確的。如果我Follow A,然后導(dǎo)航B的主頁(yè),我的組件不應(yīng)該Follow到B。這個(gè)class顯然有缺陷。

所以為什么我們class的例子展示出這樣的結(jié)果呢?

讓我們仔細(xì)研究一下class中的showMessage方法:

showMessage = () => {
  alert("Followed " + this.props.user);
};

這個(gè)方法從this.props.user取值,在React中,props應(yīng)該是不可變的,但是this卻是可變的。

實(shí)際上,在React內(nèi)部會(huì)隨著時(shí)間的推移改變this,以便可以在render和生命周期中取到最新的版本。

所以如果我們的組件在請(qǐng)求過(guò)程中re-render,this.props將會(huì)改變,showMessage方法將會(huì)從“最新”的props中取到user的值。

這就暴露了一個(gè)關(guān)于UI的有趣問(wèn)題。如果說(shuō)UI是一個(gè)關(guān)于當(dāng)前應(yīng)用state的函數(shù),那么事件處理函數(shù)就是render的一部分,就像是可視化輸出一樣。我們的事件處理函數(shù)“屬于“某一特定state和props的render。

但是在包含超時(shí)操作的回調(diào)函數(shù)內(nèi)讀取this.props會(huì)破壞這個(gè)關(guān)聯(lián)。showMessage沒(méi)有“綁定”到任何一個(gè)特定的render,因此它“丟失”了正確的props。

我們說(shuō)function components不會(huì)存在這個(gè)問(wèn)題。那么我們?cè)撛趺慈ソ鉀Q呢?

我們需要去用某種方式“修復(fù)”正確的props到showMessage之間的關(guān)聯(lián)。在執(zhí)行的某個(gè)地方,props丟失了。

一個(gè)簡(jiǎn)單的方式就是在早期我們就拿到這個(gè)this.props的值,然后顯示的去將它傳遞到超時(shí)處理函數(shù)中:

class ProfilePage extends React.Component {
  showMessage = (user) => {
    alert("Followed " + user);
  };

  handleClick = () => {
    const {user} = this.props;
    setTimeout(() => this.showMessage(user), 3000);
  };

  render() {
    return ;
  }
}

這是可行的。然而,這種方法使代碼更加冗長(zhǎng),并且隨著時(shí)間的推移更容易出錯(cuò)。如果我們需要的不僅僅是一個(gè)單一的props怎么辦?如果ShowMessage調(diào)用另一個(gè)方法,而該方法讀取this.props.something或this.state.something,我們將再次遇到完全相同的問(wèn)題。所以我們必須通過(guò)在ShowMessage調(diào)用的每個(gè)方法,將this.props和this.state作為參數(shù)傳遞。

這樣做我們通常會(huì)破壞一個(gè)class,并且會(huì)導(dǎo)致很多bug出現(xiàn)。

同樣,在handleClick中用alert展示也不能暴露出更深的問(wèn)題。如果我們想要去結(jié)構(gòu)化我們的代碼,將代碼拆分出不同的方法,并且在讀取props和state時(shí)也能保持一樣的展示結(jié)果,而且不僅僅在React中,你也可以在任何UI庫(kù)中去調(diào)用它。

也許,我們可以在構(gòu)造函數(shù)中綁定這些方法?

class ProfilePage extends React.Component {
  constructor(props) {
    super(props);
    this.showMessage = this.showMessage.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  showMessage() {
    alert("Followed " + this.props.user);
  }

  handleClick() {
    setTimeout(this.showMessage, 3000);
  }

  render() {
    return ;
  }
}

不,這并不能解決任何問(wèn)題。記住,我們的問(wèn)題是拿到this.props太晚了,而不是我們使用何種語(yǔ)法。但是,如果我們完全依賴(lài)于js的閉包,問(wèn)題就會(huì)得到解決。

閉包通常是被避免的,因?yàn)樗茈y考慮一個(gè)隨時(shí)間變化的值。但是在React中,props和state應(yīng)該是不可變的。

這意味著,如果去掉某個(gè)特定render中的props或state,則始終可以指望它們保持相同:

class ProfilePage extends React.Component {
  render() {
    // Capture the props!
    const props = this.props;

    // Note: we are *inside render*.
    // These aren"t class methods.
    const showMessage = () => {
      alert("Followed " + props.user);
    };

    const handleClick = () => {
      setTimeout(showMessage, 3000);
    };

    return ;
  }
}

已經(jīng)在render時(shí)“捕獲”到了props。

這樣,它里面的任何代碼(包括showMessage)都可以保證取到某個(gè)特定render中的props了。

然后我們可以添加很多的helper函數(shù),他們都可以捕獲到props和state。閉包救了我們。

上面的例子是正確的,但看起來(lái)很奇怪。如果只是在render中定義函數(shù)而不是使用類(lèi)方法,那么我們使用一個(gè)class又有什么意義呢?

實(shí)際上我們可以通過(guò)移除class來(lái)簡(jiǎn)化代碼:

function ProfilePage(props) {
  const showMessage = () => {
    alert("Followed " + props.user);
  };

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };

  return (
    
  );
}

就像上面所說(shuō)的,props仍然可以被捕獲到,React將它作為一個(gè)參數(shù)傳遞。不同的是,props對(duì)象本身不會(huì)因React而發(fā)生變化了。

在下面中就更明顯了:

function ProfilePage({ user }) {
  const showMessage = () => {
    alert("Followed " + user);
  };

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };

  return (
    
  );
}

當(dāng)父組件根據(jù)不同的props渲染時(shí),React將會(huì)再次調(diào)用function,但是我們點(diǎn)擊的事件處理函數(shù)是上一個(gè)包含user值的render,并且showMessage函數(shù)已經(jīng)拿到了user這個(gè)值

這就是為什么在這個(gè)版本的function demo中在Sophie主頁(yè)點(diǎn)擊Follow,然后改變select,將會(huì)alert “Followed Sophie”。

現(xiàn)在我們知道了在React中 function 和 class的最大不同。

function components捕獲渲染值(capture value)

對(duì)于鉤子,同樣的原理也適用于state??紤]這個(gè)例子:

function MessageThread() {
  const [message, setMessage] = useState("");

  const showMessage = () => {
    alert("You said: " + message);
  };

  const handleSendClick = () => {
    setTimeout(showMessage, 3000);
  };

  const handleMessageChange = (e) => {
    setMessage(e.target.value);
  };

  return (
    <>
      
      
    
  );
}

這里是在線(xiàn)demo

這個(gè)例子說(shuō)明了相同點(diǎn):在點(diǎn)擊send按鈕后,再次修改輸入框的值,3秒后的輸出依然是點(diǎn)擊前輸入框的值。這說(shuō)明function Hooks同樣具有capture value的特性。

所以我們知道了在React中function默認(rèn)情況下會(huì)捕獲props和state(capture value)。但是如果我們想要去避免這個(gè)capture value呢?

在class中,我們可以通過(guò)使用this.props和this.state,因?yàn)?b>this本事是可變的,React改變了它,在function components中,還有一個(gè)被所有組件所共享的可變值,被叫做ref

function MyComponent() {
  const ref = useRef(null);
  // You can read or write `ref.current`.
  // ...
}

但是,你必須自己管理它。

ref和實(shí)例字段有著相同的作用,你也許更為熟悉“dom refs”,但是這個(gè)概念更為普遍,它僅僅是一個(gè)“放置一些東西的通用容器”。

盡管看起來(lái)它像是某一些東西的鏡像,但實(shí)際上他們表示著相同的概念。

React默認(rèn)不會(huì)為function components創(chuàng)建保存最新props和state的refs。因?yàn)楹芏嗲闆r下你是不需要他們的,并且分配他們也很浪費(fèi)時(shí)間。但是需要的時(shí)候可以手動(dòng)的去跟蹤值:

function MessageThread() {
  const [message, setMessage] = useState("");
  const latestMessage = useRef("");

  const showMessage = () => {
    alert("You said: " + latestMessage.current);
  };

  const handleSendClick = () => {
    setTimeout(showMessage, 3000);
  };

  const handleMessageChange = (e) => {
    setMessage(e.target.value);
    latestMessage.current = e.target.value;
  };

這時(shí)我們發(fā)現(xiàn),在點(diǎn)擊send按鈕后繼續(xù)輸入,3秒后alert的是點(diǎn)擊按鈕后輸入的值而不是點(diǎn)擊按鈕錢(qián)輸入的值。

通常,應(yīng)該避免在渲染期間讀取或設(shè)置refs,因?yàn)樗鼈兪强勺兊?。我們希望保持渲染的可預(yù)測(cè)性。但是,如果我們想要獲取特定props或state的最新值,手動(dòng)更新ref可能會(huì)很煩人。我們可以通過(guò)使用一種效果來(lái)實(shí)現(xiàn)自動(dòng)化(useEffect在每次render都會(huì)執(zhí)行):

function MessageThread() {
  const [message, setMessage] = useState("");

  // Keep track of the latest value.
  const latestMessage = useRef("");
  useEffect(() => {
    latestMessage.current = message;
  });

  const showMessage = () => {
    alert("You said: " + latestMessage.current);
  };

這里是demo

我們?cè)?b>effect中進(jìn)行賦值,以便ref的值只在DOM更新后才更改。

像這樣使用ref不是經(jīng)常需要的。通常capture props或state才是默認(rèn)更好的選擇。但是,在處理諸如間隔和訂閱之類(lèi)的命令式API時(shí),它非常方便。記住,您可以跟蹤任何這樣的值:一個(gè)prop、一個(gè)state變量、整個(gè)props對(duì)象,甚至一個(gè)函數(shù)。

在本文中,我們研究了class中常見(jiàn)的中斷模式,以及閉包如何幫助我們修復(fù)它。但是,你可能已經(jīng)注意到,當(dāng)你試圖通過(guò)指定依賴(lài)數(shù)組來(lái)優(yōu)化Hooks時(shí),可能會(huì)遇到帶有過(guò)時(shí)閉包的錯(cuò)誤。這是否意味著閉包是問(wèn)題所在?我不這么認(rèn)為。

正如我們上面所看到的,閉包實(shí)際上幫助我們解決了難以注意到的細(xì)微問(wèn)題。類(lèi)似地,它們使在并發(fā)模式下正確地編寫(xiě)代碼變得更加容易。

到目前為止,我所看到的所有情況下,“過(guò)時(shí)的閉包”問(wèn)題都是由于錯(cuò)誤地假設(shè)“函數(shù)不更改”或“props總是相同”而發(fā)生的。事實(shí)并非如此,我希望這篇文章能夠幫助澄清。

function components沒(méi)有props和state,因此它們的也同樣重要。這不是bug,而是function components的一個(gè)特性。例如,函數(shù)不應(yīng)該從useEffect或useCallback的“依賴(lài)項(xiàng)數(shù)組”中被排除。(正確的解決方案通常是上面的useReducer或useRef解決方案。)

當(dāng)我們用函數(shù)編寫(xiě)大多數(shù)React代碼時(shí),我們需要調(diào)整優(yōu)化代碼的直覺(jué),以及什么值會(huì)隨著時(shí)間而改變。

正如Fredrik所說(shuō):

對(duì)于Hooks,我迄今為止發(fā)現(xiàn)的最好的規(guī)則是“代碼就像任何值在任何時(shí)候都可以改變”。

React的function總是捕捉它們的值(capture value)—— 現(xiàn)在我們知道為什么了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/102990.html

相關(guān)文章

  • Top 15 - Material Design框架和類(lèi)庫(kù)()

    摘要:這是一個(gè)用于構(gòu)建響應(yīng)式應(yīng)用和網(wǎng)站的前端框架。是基于設(shè)計(jì)的一套豐富的組件。這是一個(gè)對(duì)混合式手機(jī)應(yīng)用框架的擴(kuò)展庫(kù)。到目前為止它僅大小,而且不依賴(lài)于任何第三方的插件,它可以很輕量的被用來(lái)創(chuàng)建和應(yīng)用。 _Material design_是Google開(kāi)發(fā)的,目的是為了統(tǒng)一公司的web端和手機(jī)端的產(chǎn)品風(fēng)格。它是基于很多的原則,比如像合適的動(dòng)畫(huà),響應(yīng)式,以及顏色和陰影的使用。完整的指南詳情請(qǐng)看這里...

    Cristic 評(píng)論0 收藏0
  • Top 15 - Material Design框架和類(lèi)庫(kù)()

    摘要:這是一個(gè)用于構(gòu)建響應(yīng)式應(yīng)用和網(wǎng)站的前端框架。是基于設(shè)計(jì)的一套豐富的組件。這是一個(gè)對(duì)混合式手機(jī)應(yīng)用框架的擴(kuò)展庫(kù)。到目前為止它僅大小,而且不依賴(lài)于任何第三方的插件,它可以很輕量的被用來(lái)創(chuàng)建和應(yīng)用。 _Material design_是Google開(kāi)發(fā)的,目的是為了統(tǒng)一公司的web端和手機(jī)端的產(chǎn)品風(fēng)格。它是基于很多的原則,比如像合適的動(dòng)畫(huà),響應(yīng)式,以及顏色和陰影的使用。完整的指南詳情請(qǐng)看這里...

    phpmatt 評(píng)論0 收藏0
  • [] React組件 是采用Functional 還是 Class編寫(xiě) ?

    摘要:在里面有兩種組件類(lèi)組件和函數(shù)式組件兩者有明顯的區(qū)別比如是屬于的類(lèi)是一個(gè)函數(shù)它返回一個(gè)組件什么是先看一段代碼這是一個(gè)函數(shù)式組件它和類(lèi)組件最關(guān)鍵的區(qū)別就是函數(shù)式組件沒(méi)有和一系列的鉤子函數(shù)這也是函數(shù)式組件經(jīng)常被用作無(wú)狀態(tài)組件的原因 在React里面有兩種組件, Class components(類(lèi)組件) 和 Functional components(函數(shù)式組件).兩者有明顯的區(qū)別,比如 ...

    Integ 評(píng)論0 收藏0
  • 】為什么 React16 對(duì)開(kāi)發(fā)人員來(lái)說(shuō)是一種福音

    摘要:譯者前端小智原文就像人們對(duì)更新移動(dòng)應(yīng)用程序和操作系統(tǒng)感到興奮一樣,開(kāi)發(fā)人員也應(yīng)該對(duì)更新框架感到興奮。錯(cuò)誤邊界是一種組件。注意將作為值傳遞進(jìn)去并不會(huì)導(dǎo)致使用。如果兩者不同,則返回一個(gè)用于更新?tīng)顟B(tài)的對(duì)象,否則就返回,表示不需要更新?tīng)顟B(tài)。 譯者:前端小智 原文:medium.freecodecamp.org/why-react16… 就像人們對(duì)更新移動(dòng)應(yīng)用程序和操作系統(tǒng)感到興奮一樣,開(kāi)發(fā)人員也應(yīng)...

    kbyyd24 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

gself

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<