九個(gè)你忽略的React 無(wú)狀態(tài)組件的優(yōu)勢(shì)

譯者:zhangolve
鏈接:http://www.zcfy.cc/article/1980
原文:https://medium.com/@housecor/react-stateless-functional-components-nine-wins-you-might-have-overlooked-997b0d933dbc#.7lv7ick6a

React 0.14 引進(jìn)了一種更簡(jiǎn)單的方式來(lái)定義組件,也就是無(wú)狀態(tài)組件。這種組件使用了原生Javascript 函數(shù),下圖就是在用ES6的情況下婴梧,React 0.14 之前版本的組件寫(xiě)法和它之后對(duì)應(yīng)的組件寫(xiě)法橙弱。

前者用了27行代碼來(lái)實(shí)現(xiàn)谣殊,而后者只用了21行建椰,這當(dāng)然也沒(méi)有什么了不起的搪柑。需要說(shuō)明的是世分,由于性能方面的原因编振,右邊代碼中的sayHi 函數(shù)應(yīng)該盡量避免這樣使用。(原因見(jiàn)文末評(píng)論)

匆匆一覽,上面左右兩種代碼形式似乎并沒(méi)有太大區(qū)別踪央,但是能夠把噪音去掉就是偉大的勝利臀玄。(譯者注:本文中所說(shuō)的噪音(noise)和信號(hào)(signal)是來(lái)自于物理學(xué)中的概念。下文中其他處遇到這兩個(gè)詞畅蹂,也是如此健无,不再解釋。)

下面就是原因了液斜。

Class并無(wú)必要

誠(chéng)然累贤,我認(rèn)為圍繞著ES6 的類(lèi)的討論已經(jīng)太多了。但是少漆,我仍然認(rèn)為純函數(shù)是更加合理的臼膏,把討厭的結(jié)構(gòu)體和繼承關(guān)系去掉無(wú)疑是件好事,體現(xiàn)了它的優(yōu)勢(shì)示损。

沒(méi)有this關(guān)鍵字

就如上面的例子所示渗磅,無(wú)狀態(tài)組件只是一個(gè)函數(shù)。因此检访,所有與Javascript語(yǔ)言中this 關(guān)鍵字有關(guān)的讓人疑惑始鱼,使人討厭的情況都會(huì)避免。沒(méi)有了this 關(guān)鍵字之后脆贵,整個(gè)組件就會(huì)更加容易讓人理解医清。只需要比較一下上例中的click 事件處理器,就能明白了卖氨。

onClick={this.sayHi.bind(this)}>Say Hi</a>
onClick={sayHi}>Say Hi</a> 

需要說(shuō)明的是会烙,對(duì)于無(wú)狀態(tài)組件而言,bind這個(gè)關(guān)鍵字并非必須的双泪。將Class 去掉之后,我們也無(wú)需通過(guò)綁定來(lái)將this關(guān)鍵字與上下文聯(lián)系起來(lái)密似。 Javascript 中的 this 關(guān)鍵字給如此多的開(kāi)發(fā)者造成了困惑焙矛,能夠盡量不用this 是無(wú)狀態(tài)組件的另一個(gè)優(yōu)勢(shì)。

被迫使用最好的方法

無(wú)狀態(tài)組件是非常有用的表現(xiàn)類(lèi)組件残腌。表現(xiàn)類(lèi)組件應(yīng)該專(zhuān)注于UI層面而不是交互村斟,應(yīng)該避免在表現(xiàn)類(lèi)組件中使用狀態(tài)。狀態(tài)應(yīng)當(dāng)通過(guò)更高水平的容器類(lèi)組件抛猫,或者是通過(guò)FLUX/Redux 等等來(lái)管理蟆盹。無(wú)狀態(tài)組件不支持狀態(tài)或者生命周期。這是一件好事闺金。為什么這么說(shuō)呢逾滥?因?yàn)樗仁鼓悴辉賾卸瑁屇悴坏貌话讶萜黝?lèi)組件和表現(xiàn)類(lèi)組件分離開(kāi)來(lái)败匹。

當(dāng)然寨昙,你總是很愿意將狀態(tài)添加到表現(xiàn)類(lèi)組件之中讥巡,這也的確是一種很快的方法來(lái)實(shí)現(xiàn)一個(gè)功能。然而舔哪,無(wú)狀態(tài)組件并不支持本地狀態(tài)欢顷,你并不能夠輕而易舉地實(shí)現(xiàn)狀態(tài)。因此捉蚤,無(wú)狀態(tài)組件就自動(dòng)迫使當(dāng)前組件保持純函數(shù)形式抬驴。你也要被迫把狀態(tài)管理放到它相應(yīng)的位置:在更高水平的容器類(lèi)組件中。

高信噪比

正如上圖所示缆巧,無(wú)狀態(tài)組件寫(xiě)起來(lái)代碼量更少布持,這也就減少了噪音干擾。正如我在“Writing Code for Humans 課程” 中所討論過(guò)的那樣盅蝗,好代碼把信噪比(signal-to-noise ratio)最大化鳖链,27行代碼的組件變成了21行,縮減了大約20%的代碼量墩莫。如果你使用ES6 結(jié)構(gòu)來(lái)處理屬性(props)芙委,那么結(jié)果是幾乎所有的信號(hào)(signal)都是有用的。

import React from ‘react’; 
const HelloWorld = ({name}) => ( 
  <div>{`Hi ${name}`}</div> 
 ); 
 export default HelloWorld; 

看見(jiàn)了吧狂秦,只用了一個(gè)函數(shù)灌侣,有一個(gè)參數(shù),返回了一個(gè)標(biāo)記(markup)裂问。是不是很Nice 侧啼!那么,還能不能讓代碼量更少呢堪簿?

代碼自動(dòng)補(bǔ)全

如果你就像是我上面例子中那樣痊乾,用ES6 拆解你的屬性(props) ,那么你現(xiàn)在用到的所有的數(shù)據(jù)都只是作為一個(gè)簡(jiǎn)單的函數(shù)參數(shù)而已椭更。這也就意味著哪审,相較于基于類(lèi)(class-based)的組件,你也得到了很好的自動(dòng)補(bǔ)全代碼支持。

很容易找出來(lái)臃腫的組件和低劣的數(shù)據(jù)結(jié)構(gòu)

眾所周知虑瀑,如果一個(gè)函數(shù)有很多參數(shù)湿滓,那它就是有代碼異味的 。當(dāng)你使用ES6 架構(gòu)來(lái)組織你的無(wú)狀態(tài)組件時(shí)舌狗,這個(gè)參數(shù)列表已經(jīng)清晰地傳遞了你組件的依賴(lài)關(guān)系叽奥。因此,也就很容易找到需要更改的組件痛侍。在上面的例子中朝氓,你也可以打破這個(gè)組件結(jié)構(gòu)或者重新思考你正傳遞的數(shù)據(jù)結(jié)構(gòu)。有時(shí)候,你并不需要傳遞一長(zhǎng)串屬性膀篮,而只需要傳遞一個(gè)對(duì)象嘹狞。但是如果這些屬性不僅僅與單獨(dú)的一個(gè)對(duì)象相匹配,那么你就需要重構(gòu)你的組件誓竿,把這個(gè)組件化整為零磅网,分成若干個(gè)單獨(dú)的組件。

便于理解

正如我們所見(jiàn)筷屡,當(dāng)你看到一個(gè)無(wú)狀態(tài)組件的時(shí)候涧偷,你就知道這其實(shí)就是一個(gè)簡(jiǎn)單的函數(shù),它有相應(yīng)的屬性毙死,可以生成HTML燎潮。即便在它的render 函數(shù)內(nèi)部嵌套了很多其他的函數(shù),它在概念上仍然是很簡(jiǎn)單的扼倘。這又是無(wú)狀態(tài)組件的一個(gè)很大的優(yōu)勢(shì)所在确封。

便于測(cè)試

因?yàn)闊o(wú)狀態(tài)組件只是一個(gè)純函數(shù),你的實(shí)現(xiàn)是非常直接的再菊。給這些值對(duì)應(yīng)的屬性(props),我期望它返回這個(gè)標(biāo)記(markup)爪喘。因此對(duì)于上面的示例 HelloWorld 組件而言,我可以把'Cory' 這個(gè)值傳遞給 props.name 纠拔,這樣這個(gè)組件就可以返回一個(gè)內(nèi)部含有'Hi Cory' 的 div 了秉剑。

由于有了React 的無(wú)狀態(tài)組件,每一個(gè)組件都可以單獨(dú)進(jìn)行測(cè)試稠诲。無(wú)需模擬侦鹏,也無(wú)需狀態(tài)的操作,或者安裝用于測(cè)試的特定的庫(kù)臀叙。

表現(xiàn)

最后略水,無(wú)狀態(tài)組件會(huì)在不久之后的將來(lái)提供更加優(yōu)秀的性能表現(xiàn)。由于針對(duì)無(wú)狀態(tài)組件劝萤,無(wú)需考慮狀態(tài)或者生命周期渊涝,React 團(tuán)隊(duì)也計(jì)劃在將來(lái)的版本中去掉不必要的檢查和內(nèi)存分配。而伴隨更加優(yōu)秀的性能表現(xiàn)而來(lái)的稳其,是更好的語(yǔ)法規(guī)則驶赏,代碼更加可讀化炸卑,代碼更加易于測(cè)試既鞠。怎么樣,這么好的東西盖文,趕緊用起來(lái)吧嘱蛋!

Summary

基于以上這些原因,我們應(yīng)該在可用之處盡量使用無(wú)狀態(tài)組件。這也讓我熱愛(ài)教授React 課程 有了一個(gè)新的原因洒敏。在當(dāng)今流行的框架中龄恋,React 的無(wú)狀態(tài)組件是我見(jiàn)過(guò)的最優(yōu)雅的實(shí)現(xiàn)可復(fù)用組件的方式,沒(méi)有之一凶伙。 是的郭毕,甚至包括 Angular 2在內(nèi),通通不在話(huà)下函荣。

你們發(fā)現(xiàn)我有什么疏漏的地方显押?可以在下面評(píng)論框里留言哦!

注:

來(lái)自原文下評(píng)論:

Felipe Amorim :如果在render 方法中定義你的函數(shù)的話(huà)傻挂,你不必再考慮綁定了乘碑。但是 由于無(wú)狀態(tài)組件并不提供 shouldComponentUpdate 方法,當(dāng)創(chuàng)建新的函數(shù)的時(shí)候金拒,你也就不能阻止不必要的重新渲染了兽肤。這也就造成了性能上的問(wèn)題。

Satyajit Sahoo: 應(yīng)該盡量避免在無(wú)狀態(tài)組件內(nèi)部使用其他函數(shù)绪抛,完全可以將這些函數(shù)放到無(wú)狀態(tài)組件之外资铡,通過(guò)傳遞屬性值的方式來(lái)實(shí)現(xiàn),這將給性能帶來(lái)很大提升睦疫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末害驹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蛤育,更是在濱河造成了極大的恐慌宛官,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓦糕,死亡現(xiàn)場(chǎng)離奇詭異底洗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)咕娄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)亥揖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人圣勒,你說(shuō)我怎么就攤上這事费变。” “怎么了圣贸?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵挚歧,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我吁峻,道長(zhǎng)滑负,這世上最難降的妖魔是什么在张? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮矮慕,結(jié)果婚禮上帮匾,老公的妹妹穿的比我還像新娘。我一直安慰自己痴鳄,他們只是感情好瘟斜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著痪寻,像睡著了一般哼转。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上槽华,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天壹蔓,我揣著相機(jī)與錄音,去河邊找鬼猫态。 笑死佣蓉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的亲雪。 我是一名探鬼主播勇凭,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼义辕!你這毒婦竟也來(lái)了虾标?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤灌砖,失蹤者是張志新(化名)和其女友劉穎璧函,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體基显,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蘸吓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撩幽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片库继。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖窜醉,靈堂內(nèi)的尸體忽然破棺而出宪萄,到底是詐尸還是另有隱情,我是刑警寧澤榨惰,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布拜英,位于F島的核電站,受9級(jí)特大地震影響读串,放射性物質(zhì)發(fā)生泄漏聊记。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一恢暖、第九天 我趴在偏房一處隱蔽的房頂上張望排监。 院中可真熱鬧,春花似錦杰捂、人聲如沸舆床。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挨队。三九已至,卻和暖如春蒿往,著一層夾襖步出監(jiān)牢的瞬間盛垦,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工瓤漏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腾夯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓蔬充,卻偏偏與公主長(zhǎng)得像蝶俱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子饥漫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 目前榨呆,react組件有三種寫(xiě)法,分別是es5的createClass寫(xiě)法庸队,es6的class寫(xiě)法积蜻,以及statel...
    ZoomFunc閱讀 1,654評(píng)論 0 1
  • 本筆記基于React官方文檔,當(dāng)前React版本號(hào)為15.4.0彻消。 1. 安裝 1.1 嘗試 開(kāi)始之前可以先去co...
    Awey閱讀 7,705評(píng)論 14 128
  • 最近看了一本關(guān)于學(xué)習(xí)方法論的書(shū)浅侨,強(qiáng)調(diào)了記筆記和堅(jiān)持的重要性。這幾天也剛好在學(xué)習(xí)React证膨,所以我打算每天堅(jiān)持一篇R...
    gaoer1938閱讀 1,678評(píng)論 0 5
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí)如输,對(duì)React的特性、重點(diǎn)和注意事項(xiàng)的提取央勒、精練和總結(jié)不见,可以做為React特性...
    科研者閱讀 8,232評(píng)論 2 21
  • 深入JSX date:20170412筆記原文其實(shí)JSX是React.createElement(componen...
    gaoer1938閱讀 8,063評(píng)論 2 35