概述
Render Props
模式是一種非常靈活複用性非常高的模式,它可以把特定行為或功能封裝成一個元件,提供給其他元件使用讓其他元件擁有這樣的能力,接下來我們一步一步來看React元件中如何實現這樣的功能。
React 元件資料傳遞
React
中我們可以給一個元件傳遞一些props
並且在元件內部展示,同樣的我們也可以傳遞一些元件同樣也是行得通的,一起看一個例子
1. 元件普通資料傳遞
我們可以通過元件傳遞一些字串資料,並且在元件內部渲染
下面的程式碼很平常,我們絕大多數程式碼都是這樣。
const Foo = ({ title }) => (
<div>
<p>{title}</p>
</div>
);
class App extends React.Component {
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo title="大家好,我是土豆" />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(`app`))
複製程式碼
2. 元件上傳遞元件
更進一步,我們可以在元件上傳遞普通的HTML 標籤
和React 元件
達到複用的目的
// https://codepen.io/tudou/full/OvdrPW
const Bar = () => (<p>我是Bar元件 :)</p>);
const Foo = ({ title, component }) => (
<div>
<p>{title}</p>
{component()}
</div>
);
class App extends React.Component {
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo title={<p>大家好,我是土豆</p>} component={() => <Bar /> } />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(`app`))
複製程式碼
在上面的例子中傳遞普通的HTML 標籤
對我們複用元件沒有任何幫助,重點可以看傳遞component
這個引數,它傳遞給Foo
元件一個函式這個函式返回的是一個Bar 元件
,我們會在Foo 元件
中呼叫並且顯示component
函式中的元件。我們再來寫一個小的DEMO進行驗證。
3. 一個純粹的Render Props
例子
// https://codepen.io/tudou/full/dmawvY
const Bar = ({ title }) => (<p>{title}</p>);
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = { title: `我是一個state的屬性` };
}
render() {
const { render } = this.props;
const { title } = this.state;
return (
<div>
{render(title)}
</div>
)
}
}
class App extends React.Component {
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo render={(title) => <Bar title={title} />} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(`app`))
複製程式碼
在上面的例子中,給Foo 元件
傳遞了一個render
引數它是一個函式這個函式返回一個Bar
元件,這個函式接受一個引數title
他來自於Foo 元件
呼叫時傳遞並且我們又將title 屬性
傳遞給了Bar 元件
。經過上述的呼叫過程我們的Bar 元件
就可以共享到Foo 元件內部的
state 屬性`。
4. 通過children
傳遞
這個demo略微不同於上面通過props
傳遞,而它是通過元件的children
傳遞一個函式給Foo 元件
// https://codepen.io/tudou/full/WzPPeL
const Bar = ({ title }) => (<p>{title}</p>);
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = { title: `我是一個state的屬性` };
}
render() {
const { children } = this.props;
const { title } = this.state;
return (
<div>
{children(title)}
</div>
)
}
}
class App extends React.Component {
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo>
{(title) => (
<Bar title={title} />
)}
</Foo>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(`app`))
複製程式碼
觀察可發現只是寫法略微有些變法,我們將要傳遞的資料放到的元件的children
。實際上並無不同之處(都是傳遞一個函式)
<Foo>
{(title) => (
<Bar title={title} />
)}
</Foo>
複製程式碼
注意事項
請注意當我們的Foo 元件
繼承於React.PureComponent
的時候,我們需要避免下面這樣的寫法。不然我們的效能優化將付之東流。
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo render={(title) => <Bar title={title} />} />
</div>
);
}
複製程式碼
如果你在render
建立一個函式,在每次渲染的時候render prop
將會是一個新的值,那麼每次將會重新渲染Bar
。
正確的做法應該是在元件內部建立一個函式用於顯示元件
const Bar = ({ title }) => (<p>{title}</p>);
class Foo extends React.Component {
constructor(props) {
super(props);
this.state = { title: `我是一個state的屬性` };
}
render() {
const { render } = this.props;
const { title } = this.state;
return (
<div>
{render(title)}
</div>
)
}
}
class App extends React.Component {
// 單獨建立一個渲染函式
renderFoo(title) {
return <Bar title={title} />;
}
render() {
return (
<div>
<h2>這是一個示例元件</h2>
<Foo render={this.renderFoo} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(`app`))
複製程式碼
總結
學習瞭解Render Props
渲染模式原理,使用了render
和children
兩種不同的渲染方法。
更新詳細的官方例子請參考https://reactjs.org/docs/render-props.html
官方例子線上參考 https://codesandbox.io/embed/1075p1yov3
如果喜歡請關注
謝謝閱讀