render
属性可以实现组件之间共享代码,值是一个函数,返回一个有自身渲染逻辑的组件,结构一般如下
<DataProvider render={data => (
<h1>Hello {data.target}</h1>
)}/>
举个栗子
比如我们有一个 Cat
组件,监听鼠标xy并展示
class Cat extends React.Component {
render() {
const { mouse } = this.props
return (
<div>{ mouse.x }-{ mouse.y }</div>
)
}
}
MouseWithCat
组件监听鼠标的变化并将状态传递给 Cat
class MouseWithCat extends React.Component {
state = {
x: 0,
y: 0
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<div style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }} onMouseMove={ this.handleMouseMove }>
<Cat mouse={ this.state } />
</div>
)
}
}
这样看起来没什么问题,但是如果来了一个新的 Dog
组件,也需要实现同样的功能,那么就需要再写一遍
class MouseWithDog extends React.Component {
state = {
x: 0,
y: 0
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<div style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }} onMouseMove={ this.handleMouseMove }>
<Dog mouse={ this.state } />
</div>
)
}
}
以此类推,如果所需要的场景增多了,就会产生大量重复代码,于是 render
属性派上用场了,我们可以通过传递一个函数来决定渲染什么子组件,我们先把 Mouse
组件改变一下,通过调用父级传递的render
方法来传递自身的state
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<div style={{ width: 400, height: 400, border: '1px solid #e5e5e5' }} onMouseMove={ this.handleMouseMove }>
{/* 调用props传递的render方法 */}
{ this.props.render(this.state) }
</div>
)
}
}
class MouseTrack extends React.Component {
render() {
return (<Mouse render={ mouse => (<Cat mouse={ mouse } />) }/>)
}
}
这时候如果新增一个 Dog,Pig 都没问题,直接调用就行了
class MouseTrack extends React.Component {
render() {
{/* return (<Mouse render={ mouse => (<Pog mouse={ mouse } />) }/>) */}
return (<Mouse render={ mouse => (<Dog mouse={ mouse } />) }/>)
}
}
总结
render
属性的值是一个函数,通过函数可以传参来动态实现需要渲染的组件
当然我们还可以用高阶组件来实现组件功能的复用,高阶组件的定义是通过包裹(wrapped)被传入的React组件,经过一系列处理,最终返回一个相对增强(enhanced)的React组件,供其他组件调用
声明一个 WithMouse
的高阶组件
import Mouse from './Mouse'
import React from 'react'
export default function WithMouse(Component) {
return class extends React.Component {
render() {
return (
<Mouse render={ (mouse) => (<Component {...this.props} mouse={mouse} />) } />
)
}
}
}
在定义 Cat
组件的时候通过 WithMouse
高阶函数来增加 Cat
的功能
import React from 'react'
import WithMouse from './WithMouse'
class Cat extends React.Component {
render() {
const { mouse } = this.props
return (
<div>{ mouse.x }-{ mouse.y }</div>
)
}
}
export default WithMouse(Cat)