Render Props
模式是一種很是靈活複用性很是高的模式,它能夠把特定行爲或功能封裝成一個組件,提供給其餘組件使用讓其餘組件擁有這樣的能力,接下來咱們一步一步來看React組件中如何實現這樣的功能。html
React
中咱們能夠給一個組件傳遞一些props
而且在組件內部展現,一樣的咱們也能夠傳遞一些組件一樣也是行得通的,一塊兒看一個例子react
咱們能夠經過組件傳遞一些字符串數據,而且在組件內部渲染
下面的代碼很日常,咱們絕大多數代碼都是這樣。性能優化
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'))複製代碼
更進一步,咱們能夠在組件上傳遞普通的HTML 標籤
和React 組件
達到複用的目的bash
// 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進行驗證。app
// 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 屬性`。函數
這個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
。ui
正確的作法應該是在組件內部建立一個函數用於顯示組件
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