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)