React的組件模式
組件化開發是React的核心,學會如何利用和組織他們有助於你創建良好的設計結構。
什麽是組件?
根據react官網的解釋大致如下:
組件可以獨立的拆分你的UI試圖,他們是可以復用的,獨立的單元。
和函數類似,React中組件接收的輸入源稱為props,並且返回react元素。react元素是對UI界面的描述。你可以告訴react你期望的UI界面,剩下的工作可以交給react來處理。
我們拿乘坐計程車打比方,當你告訴司機你想要去的地方,司機就會按照你期望地點將你安全的送到目的地。而不用你自己親自開車。
Component Api‘s
react的api有哪些呢?react總共有主要的5大api他們分別是:
1.render
2.state
3.props
4.context
5.life cycle events
組件有狀態組件和無狀態組件,狀態組件使用可控制狀態的api,render state 和life cycle events。無狀態組件使用render props context。
組件設計模式,可以將你的數據層和邏輯層分開,通過職責區分你的組件。你可以創建可以復用的組件,而這些組件又可以創建出更加復雜的UI試圖。這對於構建app是極為重要的。
在組件設計模式中我們可以將組件分為:
1.容器組件
2.展示型組件
3.高階組件
4.render回調
容器組件:
容器組件用於獲取數據,渲染他下面的子組件,這個就是容器組件。
容器組件可以是你的數據層或者業務邏輯層,並且使用的是stateful api。通過生命周期函數你可以連接你的狀態管理庫,例如redux或者flux。容器組件可以傳遞數據和回調函數給子組件。在容器組件的render方法中,通過展示組件的組合來構建你的UI試圖。因為容器組件是具有狀態的,所以你需要使用class來聲明你的組件,而不是使用函數式組件。
在如下例子中,有個class component名為Greeting,他有state,生命周期函數和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> ); } }
這個組件是具備狀態的class組件。為了讓Greeting組件成為容器型組件,我們需要把UI拆分到展示型組件中。如下:
展示型組件:
展示型組件利用的是,props,render,context(stateless api‘s)
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> ); } }
如上示例,我們移除了標簽元素,並且將他放入了無狀態的展示型組件中。當然這個只是這個很簡單的示例,但是在復雜的app運用中,原理都是相同的。
高階組件:
高階組件,是以組件作為參數,並且返回一個新的組件。
高階組件可以提供數據給任意數量的組件,並且有效的復用業務邏輯。它是個強大的模式。例如在react-router和redux中,在react-router中你可以使用widthRouter()去繼承方法,並且通過props傳遞給你的組件。在redux中你可以connect方法去傳遞你的actions。
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);
如上示例,我們通過this.props.location.pathname來更新狀態。通過withRouter方法來包裹組件。現在我們的組件可以通過props來出來react-rouoter的方法this.props.location.pathname;
Render callbacks
類似於高階組件,render callbacks或者render props都是用來復用組價邏輯的。當更多的開發者傾向於高階組件來復用業務邏輯的時候,這裏有幾個原因和優點可以讓你嘗試下使用render callbacks。render callsbacks可以有效的減少命名沖突,並且清晰的展示邏輯的來源。
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中的state。
React的組件模式