React的組件模式

組件是 React 的核心,所以瞭解如何利用它們對於建立優秀的設計結構相當重要。javascript

什麼是組件

根據 React 官網的介紹,「組件讓你能夠將 UI 分割成獨立的、可重用的部分,並獨立管理每一個部分。」java

當你第一次安裝 npm install react 時,會獲得一件事:組件及其 API。與 JavaScript 函數相似,組件接受名爲 「props」 的輸入並返回 React 元素,該元素描述(聲明)用戶界面(UI)的外觀。這就是爲何 React 被稱爲聲明性 API,由於你告訴它你但願 UI 是什麼樣子的,而 React 負責其他的工做。react

能夠把聲明式想像成當打的去一個目的地時,只須要告訴司機去哪裏,他就會開車把你送到那裏。命令式編程正好相反—,你得本身駕車到那裏。npm

組件的 API

當安裝 React 後,即可以使用 React 提供的 API,基本能夠分紅 5 種。編程

  • render
  • state
  • props
  • context
  • lifecycle events

儘管一個組件可使用上述全部 API,但一個組件一般用到只有少數幾個 API,而其餘組件則只使用其餘 API。redux

能夠對組件使用不一樣的 API 對組件進行劃分,分爲 有狀態(stateful)無狀態(stateless) 兩種組件。小程序

  • 有狀態組件一般使用 API: render, state 和生命週期相關事件。
  • 無狀態組件一般使用 API: render, props 和 context。

以上就是咱們爲佬要介紹 組件模式 的緣由。組件模式是使用 React 時的最佳實踐,最初引入組件模式是爲了將數據邏輯和 UI 表現層進行分離。經過在組件之間劃分職責,您以建立更多可重用的、內聚的組件,這些組件可用於組合複雜的 UI,這在構建可擴展的應用程序時尤爲重要。微信小程序

組件模式

一般組件模式有如下幾種:微信

  • Container (容器組件)
  • Presentational (展現組件)
  • Higher order components (高級組件)
  • Render callback (渲染回調)

代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebugreact-router

Container (容器組件)

「容器組件就是取數據,而後渲染子組件而已」 —— Jason Bonta

容器組件是你的數據或邏輯層並利用 stateful API,使用生命週期事件,你能夠鏈接 stateredux 或者 Fluxstorage 中,並將數據和回調做爲 props 傳遞給子組件。

在容器組件的 render 方法中,你可使用 展現組件 來渲染具體的樣式。爲了可以訪問到全部狀態 API,容器組件必須使用 class 的方式聲明,而不是使用函數式方法聲明。

在下面的示例中,咱們有一個名爲 Greeting 的類組件,它具備狀態,生命週期事件componentDidMount()render 方法。

class Greeting extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "",
    };
  }

  componentDidMount() {
    // AJAX
    this.setState(() => {
      return {
        name: "William",
      };
    });
  }

  render() {
    return (
      <div>
        <h1>Hello! {this.state.name}</h1>
      </div>
    );
  }
}

此時,該組件是一個有狀態類組件,爲了使 Greeting 成爲一個容器組件,咱們能夠將 UI 拆分爲一個 展現組件,將在下面進行說明。

展現組件

展現組件 使用 propsrendercontext (無狀態API),而且因爲不須要使用生命週期相關 Api,可使用純函數來簡化表述它們:

const GreetingCard = (props) => {
  return (
    <div>
      <h1>Hello! {props.name}</h1>
    </div>
  )
}

展現組件 僅從 props 接收數據和回調,這些數據和回調能夠由其容器組件(父組件)提供。

容器組件和展現組件各自將數據/邏輯和展現部分封裝到各自的組件中:

const GreetingCard = (props) => {
  return (
    <div>
      <h1>{props.name}</h1>
    </div>
  )
}

class Greeting extends React.Component {
  constructor() {
    super();
    this.state = {
      name: "",
    };
  }

  componentDidMount() {
    // AJAX
    this.setState(() => {
      return {
        name: "William",
      };
    });
  }

  render() {
    return (
      <div>
       <GreetingCard name={this.state.name} />
      </div>
    );
  }
}

如你所見,已經將 Greeting 組件中展現相關的部分移動到了它本身的函數式展現組件中。固然,這是一個很是簡單的例子——對於更復雜的應用程序,這也是最基本的。

高階組件

高階組件是一種函數,它接受一個組件做爲參數,而後返回一個新的組件。

這是一種能夠對輸入組件的 props 進行修改(增刪改查)而後返回全新的修改後的組件強大模式,想一想 react-router-v4redux 。用了 react-router-v4 後,你可使用 withRouter() 來繼承以 props 形式傳遞給組件的各類方法。一樣,用了redux,就可使用 connect({})() 方法來將展現組件和 store 中的數據進行鏈接。

代碼演示:

import {withRouter} from 'react-router-dom';

class App extends React.Component {
  constructor() {
    super();
    this.state = {path: ''}
  }
  
  componentDidMount() {
    let pathName = this.props.location.pathname;
    this.setState(() => {
      return {
        path: pathName,
      }
    })
  }
  
  render() {
    return (
      <div>
        <h1>Hi! I'm being rendered at: {this.state.path}</h1>
      </div>
    )
  }
}

export default withRouter(App);

導出組件時,使用用 react-router-v4withRouter()方法封裝它。 在 組件 App 的生命週期事件 componentDidMount()方法中,咱們使用this.props.location.pathname 提供的值來更新 state。 因爲咱們使用了 withRouter 高階組件,咱們能夠直接訪問 this.props.locationlocation,而不須要直接將 location 做爲 props 直接傳入,很是方便。

渲染回調

與高階組件相似,渲染回調或渲染 props 被用於共享或重用組件邏輯。雖然許多開發人員傾向於使用 高階組件 的可重用邏輯,可是使用 渲染回調 仍然有一些很是好的理由和優點——這是在 Michael Jackson 的「永不寫另外一個高階組件」中獲得了最好的解釋。簡而言之,渲染回調減小了命名空間衝突,並更好的說明了邏輯來源。

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0,
    };
  }

  increment = () => {
    this.setState(prevState => {
      return {
        count: prevState.count + 1,
      };
    });
  };

  render() {
    return (
      <div onClick={this.increment}>{this.props.children(this.state)}</div>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <Counter>
        {state => (
          <div>
            <h1>The count is: {state.count}</h1>
          </div>
        )}
      </Counter>
    );
  }
}

Counter 類中,在 render 方法中嵌入 this.props.children 並將 this.state 做爲參數。在 App 類中,咱們能夠將咱們組件封裝在 Counter 組件中,所以我能夠操做 Counter 組件內的邏輯。

Counter 組件的本質是暴露了 children 這個外部屬性,將 children 具體的渲染細節交個 Counter 的使用者,使用的時候只須要將組件傳入到 Counterchildren 中,固然可使用其餘參數,若是 children 不夠的話。

原文:React component patterns

關於Fundebug

Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網等衆多品牌企業。歡迎你們免費試用

相關文章
相關標籤/搜索