React的元件模式
摘要: 元件是 React 的核心。
- 原文:React的元件模式
- 作者:前端小智
Fundebug經授權轉載,版權歸原作者所有。
元件是 React 的核心,因此瞭解如何利用它們對於建立優秀的設計結構至關重要。
什麼是元件
根據 React 官網的介紹,“元件讓你可以將 UI 分割成獨立的、可重用的部分,並獨立管理每個部分。”
當你第一次安裝 npm install react
時,會得到一件事:元件及其 API。與 JavaScript 函式類似,元件接受名為 “props” 的輸入並返回 React 元素,該元素描述(宣告)使用者介面(UI)的外觀。這就是為什麼 React 被稱為宣告性 API,因為你告訴它你希望 UI 是什麼樣子的,而 React 負責其餘的工作。
可以把宣告式想像成當打的去一個目的地時,只需要告訴司機去哪裡,他就會開車把你送到那裡。指令式程式設計正好相反—,你得自己駕車到那裡。
元件的 API
當安裝 React 後,便可以使用 React 提供的 API,基本可以分成 5 種。
- render
- state
- props
- context
- lifecycle events
儘管一個元件可以使用上述所有 API,但一個元件通常用到只有少數幾個 API,而其他元件則只使用其他 API。
可以對元件使用不同的 API 對元件進行劃分,分為 有狀態(stateful) 和 無狀態(stateless) 兩種元件。
- 有狀態元件通常使用 API: render, state 和生命週期相關事件。
- 無狀態元件通常使用 API: render, props 和 context。
以上就是我們為佬要介紹 元件模式 的原因。元件模式是使用 React 時的最佳實踐,最初引入元件模式是為了將資料邏輯和 UI 表現層進行分離。通過在元件之間劃分職責,您以建立更多可重用的、內聚的元件,這些元件可用於組合複雜的 UI,這在構建可擴充套件的應用程式時尤其重要。
元件模式
通常元件模式有以下幾種:
- Container (容器元件)
- Presentational (展示元件)
- Higher order components (高階元件)
- Render callback (渲染回撥)
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
Container (容器元件)
“容器元件就是取資料,然後渲染子元件而已” —— 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
Fundebug專注於JavaScript、微信小程式、微信小遊戲、支付寶小程式、React Native、Node.js和Java線上應用實時BUG監控。 自從2016年雙十一正式上線,Fundebug累計處理了10億+錯誤事件,付費客戶有Google、360、金山軟體、百姓網等眾多品牌企業。歡迎大家免費試用!
相關文章
- react 高階元件的代理模式React元件模式
- React元件設計模式(一)React元件設計模式
- TypeScript 2.8下的終極React元件模式TypeScriptReact元件模式
- React元件「設計模式」快速指南React元件設計模式
- React 元件模式學習總結React元件模式
- (譯)React 元件設計模式基礎React元件設計模式
- 【面試進階】React元件設計模式(一)面試React元件設計模式
- react篇章-React 元件-複合元件React元件
- react元件的建立React元件
- React篇章-React 元件React元件
- React元件React元件
- BLoc模式在React中使用-業務邏輯元件的獨立使用BloC模式React元件
- React router動態載入元件-介面卡模式的應用React元件模式
- react hooks 如何自定義元件(react函式元件的封裝)ReactHook元件函式封裝
- React的非同步元件React非同步元件
- react 元件的屬性React元件
- [譯] 單元素元件模式簡介:使用 React 或其它元件庫建立可靠元件的規則和實踐元件模式React
- react篇章-React 元件-向元件傳遞引數React元件
- (React啟蒙)理解React 元件React元件
- [譯] React 中的 dumb 元件和 smart 元件React元件
- React拖拽元件React元件
- React高階元件的使用React元件
- 獲取React元件的DOMReact元件
- React構建元件的方式React元件
- React元件複用的方式React元件
- react複合元件的使用React元件
- React中的高階元件React元件
- vue與react元件的思考VueReact元件
- 說說React元件的StateReact元件
- 拖拽元件:React DnD 的使用元件React
- [React]元件的生命週期React元件
- [譯] React 路由和 React 元件的愛恨情仇React路由元件
- React Native 元件(一)元件的生命週期React Native元件
- react元件(react-grid-gallery)React元件
- React受控元件和非受控元件React元件
- Chat-React基於react的聊天會話元件React會話元件
- React 基礎_元件React元件
- React 非同步元件React非同步元件