[譯] 設計 React 組件 API

多年來,我致力於一系列處理組件 API 和構建應用程序、庫的模式。如下是一系列如何設計組件 API 的想法、觀點和建議,這會讓組件更靈活、更具備組合性、更容易理解。這些規則都不是硬性的,但它們幫助我想明白瞭如何組織和建立組件。html

提供最少的 API

正如 React 庫自己的目標是 最少化 API 同樣,我建議在設計組件 API 時採用相似的觀點。須要學習的新內容越少,其餘人就越容易知道如何使用你建立的組件,從而使它們更容易被重用。若是有人不理解你的組件 API,那麼他們重複你的工做的可能性就會增長。這是我如何建立組件的核心理念,我發如今我工做中牢記它頗有幫助。前端

讓你的代碼更容易被找到

從扁平目錄結構開始,不要過早地組織代碼庫。人類喜歡整理東西,但咱們在這方面作得很糟糕。命名已經足夠困難了,爲組件庫建立目錄結構,您可能會作更多的工做,最終使其餘人更難找到你所寫的代碼。react

一個單獨存放組件的目錄在變得難以管理以前會變得至關大。若是全部的組件都在一個文件夾中,在大多數文件系統工具中會自動按照字母進行排序,這有助於爲其餘人提供更完整的代碼庫概覽。android

避免 renderXXX 方法

若是您在組件中定義了以 render 開頭的自定義方法,那麼它極可能應該被定義爲自有組件。正如 Chris Biscardi 所說,「高效意味着有有足夠的複雜度值得被分解」。React 能明智地決定是否渲染的時機,所以,將這些組件拆分爲自有組件,能夠幫助 React 更好地運行。ios

// 不要這樣寫
class Items extends React.Component {
  renderItems ({ items }) {
    return items.map(item => (
      <li key={item.id}> {renderItem(item)} </li>
    ))
  }

  renderItem (item) {
    return (
      <div> {item.name} </div>
    )
  }

  render () {
    return (
      <ul> {renderItems(this.props) </ul>
    )
  }
}
複製代碼
// 這樣寫
const ItemList = ({ items }) =>
  <ul>
    {items.map(item => (
      <li key={item.id}>
        <Item {...item} />
      </li>
    )}
  </ul>

const Item = ({ name }) =>
  <div>{item.name}</div>

class Items extends React.Component {
  render () {
    const { items } = this.props
    return <ItemList items={items} />
  }
}
複製代碼

在數據界限上分割組件

一般,組件應該由數據的形狀來定義git

既然你常常向用戶展現 JSON 數據模型,你會發現,若是你的模型構建正確,你的 UI(以及你的組件結構)會被很好地映射。github

我常常看到 React 新手嘗試複製我所說的 "Bootstrap" 組件,即具備視覺邊界,但與任何數據結構都沒有直接聯繫的 UI 組件。React 組件和 BEM 風格、基於 CSS 的組件有着不一樣的關注點。不該該建立一個須要定製 props 的通用 Card 組件來顯示圖像、標題和連接,而是爲你須要展現的數據建立組件。也許通用的 Card 組件應該是一個接受來自數據庫的 product 對象的 ProductCard 組件。數據庫

// 不要這樣寫
<Card
  image={product.thumbnail}
  title={product.name}
  text={product.description}
  link={product.permalink}
/>

// 這樣寫
<ProductCard {...product} />
複製代碼

極可能,你須要的 ProductCard 的特定樣式並不都是可重用的,並且你可能只在代碼庫中的一個地方定義了這個樣式。在這種狀況下,你能夠遵循 三次法則。若是你已經在代碼庫中複製了三次 Card 組件結構,那麼將其抽象出自有組件多是值得的。bootstrap

避免繁多的 props

正如 Jenn Creighton 所說,避免 繁多的 props。不要懼怕建立一個新的組件,而不是向組件添加一些任意的 props 和附加的邏輯。例如,Button 組件能夠接受不一樣顏色、大小和形狀的 props,但並不老是須要這麼多的 props。後端

// 不要這要寫
<Button
  variant='secondary'
  size='large'
  outline
  label='Buy Now'
  icon='shoppingBag'
  onClick={handleClick}
/>

// 這要寫
<SecondaryButton
  size='large'
  onClick={handleClick}>
  <Icon name='shoppingBag' /> Buy Now </SecondaryButton>
複製代碼

你的需求可能會有所不一樣,可是減小組件所需的自定義 props 的數量一般頗有幫助,而且減小 render 函數中的邏輯數量可使代碼庫更簡單,更適合於代碼分割。

使用組合

不要從新發明 props.children。若是你已經定義了 props 接收不基於數據結構的任意文本字符串,那麼最好使用組合。

// 不要這樣寫
<Header
  title='Hello'
  subhead='This is a header'
  text='And it has arbitrary props'
/>

// 這樣寫
<Header>
  <Heading>Hello</Heading>
  <Subhead>This is a header</Subhead>
  <Text>And it uses composition</Text>
</Header>
複製代碼

若是你熟悉 React,那麼你可能已經知道了組合版本組件的 API,它不會像以前那樣須要那麼多的文檔。在你的應用中,你能夠將組合版本的組件封裝到另外一個與數據結構綁定組件中,並且你可能只須要在代碼庫中定義一次組件結構。

// 對於一個基於數據的組件而言,這樣寫頗有用
const PageHeader = ({
  title,
  description
}) =>
  <Header> <Heading>{title}</Heading> <Text>{description}</Text> </Header>

// 理想狀況下能夠這樣使用
<PageHeader {...page} />
複製代碼

避免枚舉布爾 props

使用 布爾 props 是一種在組件變量之間進行切換的便捷方式,這頗有吸引力,但它有時會產生一個使人困惑的 API。 查看下面的例子:

<Button primary />
<Button secondary /> 複製代碼

下面的狀況會發生什麼?

<Button primary secondary />
複製代碼

若是不深刻到代碼庫或文檔中,就沒法理解。相反,試試如下:

<Button variant="primary" />
複製代碼

這樣須要打更多的字,可是能夠說更加具備可讀性。

保持 props 並行

只要有可能,複用其餘組件的 props。例如,若是你正在寫一個日期選擇器,請使用與原生 <input type='date' /> 相同的 props。這樣將更容易猜想組件是如何運做的,也更容易記住這些 API。

// 不要這樣寫
<DatePicker
  date={date}
  onSelect={handleDateChange}
/>

// 這樣寫
<DatePicker
  value={date}
  onChange={handleDateChange}
/>
複製代碼

Styled System 庫鼓勵跨多個組件使用並行風格的 props API。例如,color props 對 Rebass 中的全部組件都起做用,最終達到一次學習,處處使用的效果。

// 來自 Rebass 的例子
<Box color='tomato' />
<Heading color='tomato' /> 複製代碼

和你的隊友溝通

這些只是我本身對如何設計組件 API 的一些想法,它們可能沒法知足您的需求。我能給出的最好建議是與你的隊友溝通,建立 RFC 和 PR,並嘗試 Readme 驅動開發。編寫 React 組件很容易。爲你的團隊建立一個運行良好的組件庫花費時間和精力是很是值得的。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索