[譯]React核心概念3:組件&props

原文連接:reactjs.org/docs/compon…html

引言

組件將UI劃分紅獨立的,可複用的片斷,並對每一個組件進行獨立的構思。本節將會介紹組件的構建思路。react

概念上來講,組件就好像是JavaScript裏的函數。它們可以接受任意的入參(稱做props)並返回描述屏幕展現UI的React元素。數組

函數組件&類組件

定義組件最簡單的方法就是寫一個JavaScript函數。bash

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

不用擔憂,這是一個可以使用的組件,由於它接收了一個帶有數據的props(也能夠用properties代替)做爲參數對象而且返回了一個React元素。咱們把這種組件成爲函數組件(由於這就是一個函數)。網絡

您也可使用ES6 class來定義組件。app

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

上述兩個組件從React的組件定義來看是等價的。函數

類組件還有一些特性咱們將會放到下一節講解。在那以前咱們將使用函數組件來進行示例講解。網站

渲染組件

以前咱們講的都只是用React元素來表明DOM標籤。ui

const element = <div />;
複製代碼

然而,React元素也能夠表示用戶定義的組件。this

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')
);
複製代碼

讓咱們回顧一下在上面這個例子裏發生了上面:

  1. 咱們在調用ReactDOM.render()函數時將 <Welcome name="Sara" />做爲參數傳遞給了它。
  2. React在調用Welcome組件時把{name:"Sara"}做爲props傳遞給他。
  3. Welcome組件返回了<h1>Hello, Sara</h1>
  4. React Dom更新了DOM以匹配<h1>Hello, Sara</h1>

提示:定義組件時組件名要以大寫字母開頭 React將以小寫字母開頭的組件視爲DOM標籤,例如<div/>表示一個HTML的 div 標籤。可是<Welcome />表示組件而且要在做用域範圍內使用它。

組合組件

組件能在它的返回元素中使用其餘組件。這使得咱們能夠在任意層級上使用組件。按鈕、表單、對話框、界面,在React應用中上述這些都被視爲組件。

例如,咱們能夠定義一個App組件,並在其中屢次引用Welcome

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

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

ReactDOM.render(
  <App />,
  document.getElementById('root')
);
複製代碼

當您使用create-react-app建立一個React應用時,您會發如今應用中App組件做爲頂層組件被使用。可是若是您是在現有應用中整合React,那麼您能夠自底向上地從使用一個小組件開始,逐步地將React組件應用到您應用的各個層級上。

提取組件

不要懼怕將組件分解成更小的組件。

舉個例子,讓咱們觀察下面的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(object),text(string),date(date)做爲props,而且描述了社交網站上的一個評論。

因爲這個組件嵌套了太多層的內容,而且其中的內容很難複用。因此,讓咱們來從中提取組件吧。

首先,咱們來提取Avatar組件。

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

Avatar組件不須要知道它是否被渲染在Comment組件裏,所以在這裏咱們將它的prop起了一個更普適的名字user

咱們推薦在給prop起名時從組件的角度上考慮,而不是從使用組件的上下文的聯想上考慮。

如今咱們在編寫Comment組件時能夠方便一點了。

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組件來渲染帶有名字的頭像。

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>
  );
}
複製代碼

在提取組件時您可能會感受到很枯燥,可是這是值得的尤爲是您正在編寫一個大型的應用時,這會節省您不少的時間。提取組件的一個標準就是若是您UI中的一部分須要使用屢次(就像ButtonPanelAvatar),或者這個頁面/組件自己很複雜時,那麼您就能夠把他提取成組件了。

Props是隻讀的

無論您是聲明瞭一個函數組件仍是類組件,它的props是不能更改的。咱們來觀察下面的代碼。

function sum(a, b) {
  return a + b;
}
複製代碼

這樣的函數稱爲純函數,由於它們不會改變它們的入參,而且在相同的入參下永遠返回相同的結果。

相反,下面的函數就不是純函數,由於它改變了它的入參。

function withdraw(account, amount) {
  account.total -= amount;
}
複製代碼

React很是靈活,可是卻有一個嚴格的規則:

全部的組件都必須想純函數同樣保護它們的props不被更改

不過,UI是動態的而且老是在改變,在下一節,咱們將會介紹一個新概念「狀態(state)」。狀態可讓組件在不違反上述規則的狀況下更具用戶的動做或者網絡傳輸結果改變輸出。

相關文章
相關標籤/搜索