天天看點

React 中的 元件、Prop 和 State

蓋房子

要想了解這些概念是什麼以及如何使用它們,我們先來寫一個小示例。就蓋個房子如何?

React 中的 元件、Prop 和 State

元件

如果你還記得我們在前面文章中所讨論過的,元件的概念是 React 的三大支柱之一。使用 React 開發應用基本都是在使用元件。

第一步是将 UI 分解成多個元件。例如,我們可以這樣來拆分房子:

React 中的 元件、Prop 和 State

現在來編碼!

House:

  <div>

    <Roof />     // 房頂

    <Wall />     // 牆

    <Window />   // 窗

    <Door />     // 門

  </div>
           

等一下,怎麼看起來這麼像 HTML ?沒錯!React 的部分代碼看上去就是非常像 HTML ,其實就是這樣設計的,這是為了讓 Web 設計師了解和編寫 React 代碼更容易一些。太貼心了!

是以,在上面的代碼中,我們使用

<div>

作為容器,這基本和 HTML 中是一樣的。而像 Roof 和 Wall 這樣的标簽是我們即将定義的自定義标簽/元件。

溫馨提示: 上面的代碼并非實際的 React 代碼,甚至連 JavaScript 都算不上。暫時,我們隻使用這種寬松的文法來介紹概念。一旦你了解這些概念後,我們再來學習 JavaScript 的細節并将上述概念轉換成真實代碼。

為了讓這個例子更容易了解一些,我再簡化一下: 從現在開始,我們來寫一個超級簡單的 Web 應用,連圖檔都不用,隻顯示文字。

例如,Roof 其實就是一個裡面有文字的 div :

Roof:

  <div>roof</div>
           

其他元件也是如此,都是隻有文字的 div 而已。首先,我們來看下房子的完整的 React 風格的代碼:

House:

  <div>

    <Roof />

    <Wall />

    <Window />

    <Door />

  </div>  

Roof:

  <div>roof</div>

Wall:

  <div>wall</div>

Window:

  <div>window</div>

Door:

  <div>door</div>
           

這沒什麼不好了解的,是吧?House 是由 Roof、Wall、Window 和 Door 組成的,這些都是純文字構成的元件。

最後,React 生成的 HTML 如下所示:

<div>

  <div>roof</div>

  <div>wall</div>

  <div>windows</div>

  <div>door</div>

</div>
           

使用 Props 來配置屋頂的顔色

想象一下,我們将規格說明書發給一個工廠,這個工廠負責代工所有的零部件。在規格說明書中,我們可以告訴工廠每個部件的固有屬性,比如屋頂的顔色、門的形狀,等等。在按照我們的要求将屋頂和門生産出來後,它們的屬性不會産生任何變化,屋頂還是藍色的,門依舊是矩形的。這些屬性壓根不會改變。

在 React 裡,我們将這些屬性稱之為 Prop ,即 property 的縮寫。關于 Prop ,你需要記住兩點: 首先,我們來決定 Prop 的值,并在元件建構之前将其作為元件設計的一部分。其次,Prop 的值永遠不會改變。

那 prop 在代碼中是怎樣的呢?在 House 元件中,如果我們想要藍色屋頂的話,隻需在 Roof 元件上添加 “color” 屬性。這就好比是在發給工廠的規格說明書中指定顔色。

這有點類似于給 HTML 标簽添加屬性:

House:

  <div>

    <Roof color="blue"/>

    ...

  </div>
           

那Roof裡面又是怎麼樣使用 prop 的呢?代碼如下所示:

Roof:

  <div>{props.color} roof</div>
           

就這樣?沒錯!但是有幾點需要注意:

定義元件的 HTML 風格代碼是一個模闆,而不是單純的 HTML 标簽。這意味着我們可以在其中放置占位符來改變 HTML 輸出的内容,而不必重複編寫不同的 HTML (還記得 Domo 的帽子嗎?這就是占位符的概念!)。在這個示例中,

<Roof color="blue" />

生成的 HTML 是

<div>blue roof<div>

,而

<Roof color="red" />

生成的是

<div>red roof</div>

,以此類推。

模闆中使用的花括号告訴 React 我們要在此處使用占位符來替代純文字。

props 可以看作是 Roof 元件所有屬性值的集合。假設元件是這樣使用的:

<Roof color="blue" material="wood" />

,那麼在 Roof 元件的定義中就可以使用

props.color

props.material

使用 State 來開門

為元件添加 State

元件還可以擁有 state 。那麼什麼是 state ?state 是一種可以在元件建立後更改的資料。

舉個例子,門既可以開,又可以關。我們可以說門的狀态就是 state ,因為它的值是可以在門建立後更改的。在這點上,state 與 prop 是不同的,prop 是不會改變的,比如門的形狀。

狀态值的改變通常是由外部事件所引起的。在 Web 應用中,這些所謂的外部事件通常包括:使用者輸入了資料,或者從服務端擷取了資料,又或者是定時器的觸發。

下面,我們來為門添加 state :

Door:

  State:

    status   // "open" 或 "closed"

  <div>Door is {state.status}</div>
           

與 props 類似,state 也是元件内部所有狀态值的集合。是以,我們可以在元件定義的模闆中使用 state.[something] 。

接下來,我們來添加一些處理使用者輸入的“僞代碼”來讓門具有互動性。

Door:

State:

  status // "open" 或 "closed"

  <div>Door is {state.status}</div>

  // 處理使用者輸入

  當開門時

    将 state.status 修改成 "open"

  當關門時

    将 state.status 修改成 "closed"
           

這裡的關鍵點是元件的 state 是随時間而變化的。模闆的輸出,也就是生成的 HTML 會根據 state 的變化而自動改變。

順便說句,不要忘了上面的隻是“僞代碼”,而不是 React 代碼。不要嘗試将其複制黏貼到你的項目中!否則你的電腦炸了我不負責……

State 是私有的

元件的 state 是私有的。門無論是開還是關,這都僅僅是門的邏輯。與房子或其他元件沒有任何關系。事實上,我們完全可以将門從房子中移出去,它仍然可以自己打開或關閉。

是以,門的狀态隻有在 Door 元件内部是可見的。在 Door 元件内,我們可以讀取或改寫它的 state 。

House:

  <div>

    <Door />

    ...

    <!-- 下面這句是錯的 -->

    <div>The door is {Door.state.status}</div>

  </div>

Window:

  ...

  <!-- 下面這句是錯的! -->

  将 Door.state.status 修改成 'open'

Door:

  ...

  <!-- 兄dei,這還是錯的! -->

  if House.state.正在出售

    房産經紀人就可以開門
           

總結

好啦,這就是 prop 和 state 。prop 是元件的配置項,它的值是在元件建立之前就已經決定好了,比如門的形狀和屋頂的顔色就以定義為 prop。prop 的值永遠不會改變。而 state 是元件的私有資料,當元件建立後才可以使用它。比如門的開關狀态可以包括在 state 裡面。state 會随着一些外部事件的發生而變化。這些所謂的外部事件通常包括:使用者輸入了資料,或者從服務端擷取了資料,又或者是定時器的觸發。

但…是,我們還沒有開發任何實際的東西啊?一個隻顯示純文字的應用能有多大用處呢?至少要學到如何建造本文開頭所說的房子吧?界面裡有東西可以點才有用啊?