組件是 React 的核心,所以瞭解如何利用它們對於建立優秀的設計結構相當重要。javascript
根據 React 官網的介紹,「組件讓你能夠將 UI 分割成獨立的、可重用的部分,並獨立管理每一個部分。」java
當你第一次安裝 npm install react
時,會獲得一件事:組件及其 API。與 JavaScript 函數相似,組件接受名爲 「props」 的輸入並返回 React 元素,該元素描述(聲明)用戶界面(UI)的外觀。這就是爲何 React 被稱爲聲明性 API,由於你告訴它你但願 UI 是什麼樣子的,而 React 負責其他的工做。react
能夠把聲明式想像成當打的去一個目的地時,只須要告訴司機去哪裏,他就會開車把你送到那裏。命令式編程正好相反—,你得本身駕車到那裏。npm
當安裝 React 後,即可以使用 React 提供的 API,基本能夠分紅 5 種。編程
儘管一個組件可使用上述全部 API,但一個組件一般用到只有少數幾個 API,而其餘組件則只使用其餘 API。redux
能夠對組件使用不一樣的 API 對組件進行劃分,分爲 有狀態(stateful) 和 無狀態(stateless) 兩種組件。小程序
以上就是咱們爲佬要介紹 組件模式 的緣由。組件模式是使用 React 時的最佳實踐,最初引入組件模式是爲了將數據邏輯和 UI 表現層進行分離。經過在組件之間劃分職責,您以建立更多可重用的、內聚的組件,這些組件可用於組合複雜的 UI,這在構建可擴展的應用程序時尤爲重要。微信小程序
一般組件模式有如下幾種:微信
代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug。react-router
「容器組件就是取數據,而後渲染子組件而已」 —— Jason Bonta
容器組件是你的數據或邏輯層並利用 stateful API,使用生命週期事件,你能夠鏈接 state
到 redux
或者 Flux
的 storage
中,並將數據和回調做爲 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 拆分爲一個 展現組件,將在下面進行說明。
展現組件 使用 props
、render
和 context
(無狀態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-v4 和 redux 。用了 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-v4 的 withRouter()
方法封裝它。 在 組件 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
的使用者,使用的時候只須要將組件傳入到 Counter
的 children
中,固然可使用其餘參數,若是 children
不夠的話。
Fundebug專一於JavaScript、微信小程序、微信小遊戲、支付寶小程序、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟件、百姓網等衆多品牌企業。歡迎你們免費試用!