渲染属性(Render Props)
用于使用一个值为函数
的 prop
在 React 组件之间
的代码共享
(数据共享
)
带有渲染属性(Render Props)的组件需要一个返回 React 元素并调用它的函数
,而不是实现自己的渲染逻辑
。
1 2 3
| <DataProvider render={data => ( <h1>Hello {data.target}</h1> )}/>
|
组件是React 主要的代码复用单元,但如何共享状态
或一个组件的行为封装到其他需要相同状态的组件中
并不是很明了
下面的组件在 web
应用追踪鼠标位置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; }
handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); }
render() { return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}> <h1>Move the mouse around!</h1> <p>The current mouse position is ({this.state.x}, {this.state.y})</p> </div> ); } }
|
在不使用render props时别的组件想使用鼠标坐标时只能包含Mouse组件或者用Mouse组件包含:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| class MouseTracker extends React.Component { render() { return ( <div> <h1>Move the mouse around!</h1> <Mouse /> </div> ); } }
class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; }
handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); }
render() { return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}> <Cat mouse={this.state} /> </div> ); } }
|
使用 render prop:
提供一个带有函数 prop
的 <Mouse>
组件,它能够动态决定什么需要渲染的,而不是将 <Cat>
硬编码到 <Mouse>
组件里
1 2 3 4 5 6 7 8 9
| class Cat extends React.Component { render() { const mouse = this.props.mouse; return ( <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} /> ); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Mouse extends React.Component { constructor(props) { super(props); this.handleMouseMove = this.handleMouseMove.bind(this); this.state = { x: 0, y: 0 }; }
handleMouseMove(event) { this.setState({ x: event.clientX, y: event.clientY }); }
render() { return ( <div style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
{
} {this.props.render(this.state)} </div> ); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class MouseTracker extends React.Component { render() { return ( <div> <h1>Move the mouse around!</h1> { <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> </div> ); } }
|
虽然这一模式被称为 “render props”
,但是函数类型的 prop``不必非叫render
,可以叫任何名称
1 2 3
| <Mouse aaa={mouse => ( <p>The mouse position is {mouse.x}, {mouse.y}</p> )}/>
|
不是必须返回一个 JSX 元素。相反,你可以直接返回一个元素!
1 2 3 4 5
| <Mouse> {mouse => ( <p>The mouse position is {mouse.x}, {mouse.y}</p> )} </Mouse>
|
兼容写法(避免了render prop
抵消 React.PureComponent
带来的优势)
将render函数 定义为父组件内部的函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| class MouseTracker extends React.Component { constructor(props) { super(props); this.renderTheCat = this.renderTheCat.bind(this); }
renderTheCat(mouse) { return <Cat mouse={mouse} />; }
render() { return ( <div> <h1>Move the mouse around!</h1> <Mouse render={this.renderTheCat} /> </div> ); } }
|