概述 模式是一種非常靈活復用性非常高的模式,它可以把特定行為或功能封裝成一個組件,提供給其他組件使用讓其他組件擁有這樣的能力,接下來我們一步一步來看React組件中如何實現這樣的功能。 React 組件數據傳遞 中我們可以給一個組件傳遞一些 並且在組件內部展示,同樣的我們也可以傳遞一些組件同樣也是行 ...
概述
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
如果喜歡請關註
謝謝閱讀