深入了解React的概念之一:組件

React 應用都是構(gòu)建在組件之上互躬。
組件可以將UI切分成一些的獨立的捺萌、可復用的部件,這樣你就只需專注于構(gòu)建每一個單獨的部件瞧柔。

組件從概念上看就像是函數(shù):
它可以接收任意的輸入值(稱之為“props”),并返回一個需要在頁面上展示的React元素睦裳。

一造锅、函數(shù)定義/類定義組件

注意: React 組件的名字必須定義為大寫開頭(比如以下的Welcome):因為利用 JSX 編寫 DOM 結(jié)構(gòu),可以用原生的 HTML 標簽廉邑,也可以直接像普通標簽一樣引用 React 組件哥蔚。這兩者約定通過大小寫來區(qū)分,小寫的字符串是 HTML 標簽蛛蒙,大寫開頭的變量是 React 組件糙箍。

1. 函數(shù)定義

定義一個組件最簡單的方式是使用JavaScript函數(shù):

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

該函數(shù)是一個有效的React組件,它接收一個單一的“props”對象并返回了一個React元素牵祟。我們之所以稱這種類型的組件為函數(shù)定義組件深夯,是因為從字面上來看,它就是一個JavaScript函數(shù)诺苹。

2. 類定義組件

也可以使用 ES6 class 來定義一個組件:

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

一般來說咕晋,一個組件類由 extends Component 創(chuàng)建,并且提供一個 render 方法以及其他可選的生命周期函數(shù)筝尾、組件相關(guān)的事件或方法來定義捡需。

二办桨、組件渲染

在前面筹淫,我們遇到的React元素都只是DOM標簽:

const element = <div />;

然而,React元素也可以是用戶自定義的組件:

const element = <Welcome name="Sara" />;

當React遇到的元素是用戶自定義的組件,它會將JSX屬性作為單個對象傳遞給該組件损姜,這個對象稱之為“props”饰剥。

例如,這段代碼會在頁面上渲染出”Hello,Sara”:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

我們來回顧一下在這個例子中發(fā)生了什么:

  • 我們對<Welcome name="Sara" />元素調(diào)用了ReactDOM.render()方法。
  • React將{name: 'Sara'}作為props傳入并調(diào)用Welcome組件摧阅。
  • Welcome組件將<h1>Hello, Sara</h1>元素作為結(jié)果返回汰蓉。
  • React DOMDOM更新為<h1>Hello, Sara</h1>

警告:
組件名稱必須以大寫字母開頭棒卷。
例如顾孽,<div /> 表示一個DOM標簽,但 <Welcome /> 表示一個組件比规,并且在使用該組件時你必須定義或引入它若厚。


三、組合組件

組件可以在它的輸出中引用其它組件蜒什,這就可以讓我們用同一組件來抽象出任意層次的細節(jié)测秸。在React應用中,按鈕灾常、表單霎冯、對話框、整個屏幕的內(nèi)容等钞瀑,這些通常都被表示為組件沈撞。

例如,我們可以創(chuàng)建一個App組件仔戈,用來多次渲染W(wǎng)elcome組件:

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}

// 省略了const element = <App />;
ReactDOM.render(
  <App />,
  document.getElementById('root')
);

通常关串,一個新的React應用程序的頂部是一個App組件。但是监徘,如果要將React集成到現(xiàn)有應用程序中晋修,則可以從下而上使用像Button這樣的小組件作為開始,并逐漸運用到視圖層的頂部凰盔。

警告:
組件的返回值只能有一個根元素墓卦。這也是我們要用一個<div>來包裹所有<Welcome />元素的原因。


四户敬、提取組件

你可以將組件切分為更小的組件落剪,這沒什么好擔心的。

例如尿庐,來看看這個Comment組件:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <img className="Avatar"
          src={props.author.avatarUrl}
          alt={props.author.name}
        />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

這個組件接收author(對象)忠怖、text(字符串)、以及date(Date對象)作為props抄瑟,用來描述一個社交媒體網(wǎng)站上的評論凡泣。

這個組件由于嵌套,變得難以被修改,可復用的部分也難以被復用鞋拟。所以讓我們從這個組件中提取出一些小組件骂维。

首先,我們來提取Avatar組件:

function Avatar(props) {
  return (
    <img className="Avatar"
      src={props.user.avatarUrl}
      alt={props.user.name}
    />
  );
}

Avatar作為Comment的內(nèi)部組件贺纲,不需要知道是否被渲染航闺。因此我們將author改為一個更通用的名字user

我們建議從組件自身的角度來命名props猴誊,而不是根據(jù)使用組件的上下文命名潦刃。

現(xiàn)在我們可以對Comment組件做一些小小的調(diào)整:

function Comment(props) {
  return (
    <div className="Comment">
      <div className="UserInfo">
        <Avatar user={props.author} />
        <div className="UserInfo-name">
          {props.author.name}
        </div>
      </div>
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

接下里,我們要提取一個UserInfo組件懈叹,用來渲染Avatar旁邊的用戶名:

function UserInfo(props) {
  return (
    <div className="UserInfo">
      <Avatar user={props.user} />
      <div className="UserInfo-name">
        {props.user.name}
      </div>
    </div>
  );
}

這可以讓我們進一步簡化Comment組件:

function Comment(props) {
  return (
    <div className="Comment">
      <UserInfo user={props.author} />
      <div className="Comment-text">
        {props.text}
      </div>
      <div className="Comment-date">
        {formatDate(props.date)}
      </div>
    </div>
  );
}

提取組件一開始看起來像是一項單調(diào)乏味的工作福铅,但是在大型應用中,構(gòu)建可復用的組件完全是值得的项阴。當你的UI中有一部分重復使用了好幾次(比如滑黔,ButtonPanel环揽、Avatar)略荡,或者其自身就足夠復雜(比如,App歉胶、FeedStory汛兜、Comment),類似這些都是抽象成一個可復用組件的絕佳選擇通今,這也是一個比較好的做法粥谬。

個人總結(jié)注意點:

  • 構(gòu)造函數(shù)是唯一初始化state的地方
  • 要更改狀態(tài)必須調(diào)用 this.setState({ });
  • 如果用props和state來計算的值,接收函數(shù)而不是對象this.setState((prevState, props) => ({}));


參考資料

  1. React 中文文檔
  2. React 文檔中文翻譯
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辫塌,一起剝皮案震驚了整個濱河市漏策,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌臼氨,老刑警劉巖掺喻,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異储矩,居然都是意外死亡感耙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門持隧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來即硼,“玉大人,你說我怎么就攤上這事屡拨≈凰郑” “怎么了题诵?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長层皱。 經(jīng)常有香客問我,道長赠潦,這世上最難降的妖魔是什么叫胖? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮她奥,結(jié)果婚禮上瓮增,老公的妹妹穿的比我還像新娘。我一直安慰自己哩俭,他們只是感情好绷跑,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凡资,像睡著了一般砸捏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隙赁,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天垦藏,我揣著相機與錄音,去河邊找鬼伞访。 笑死掂骏,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的厚掷。 我是一名探鬼主播弟灼,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼冒黑!你這毒婦竟也來了田绑?” 一聲冷哼從身側(cè)響起棋凳,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤皂冰,失蹤者是張志新(化名)和其女友劉穎渊胸,沒想到半個月后房轿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芙代,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡丐重,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年惯殊,在試婚紗的時候發(fā)現(xiàn)自己被綠了携御。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诱咏。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡苔可,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出袋狞,到底是詐尸還是另有隱情焚辅,我是刑警寧澤映屋,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站同蜻,受9級特大地震影響棚点,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜湾蔓,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一瘫析、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧默责,春花似錦贬循、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至媒熊,卻和暖如春奇适,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芦鳍。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工滤愕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怜校。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓间影,卻偏偏與公主長得像,于是被迫代替她去往敵國和親茄茁。 傳聞我的和親對象是個殘疾皇子魂贬,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 做React需要會什么付燥? react的功能其實很單一,主要負責渲染的功能愈犹,現(xiàn)有的框架键科,比如angular是一個大而...
    蒼都閱讀 14,759評論 1 139
  • 以下內(nèi)容是我在學習和研究React時,對React的特性漩怎、重點和注意事項的提取勋颖、精練和總結(jié),可以做為React特性...
    科研者閱讀 8,232評論 2 21
  • 學習如何在Flow中使用React 將Flow類型添加到React組件后勋锤,F(xiàn)low將靜態(tài)地確保你按照組件被設計的方...
    vincent_z閱讀 6,353評論 4 21
  • 燕子捎春意 繁花寄綠時 唯羨晴時月 獨攬九霄云
    宗宣先生閱讀 230評論 0 1
  • 10.18日饭玲,我和舍友劍人在住處附近的一家書店閑逛,碰到了基本有意思的書籍叁执。有一套叢書茄厘,《三體》(1-3)矮冬,很想買...
    Leo小福閱讀 184評論 0 1