含义:
是一种在React中,复用/共享代码(组件)的一种技术。
传统做法:
MouseWithCat组件可以跟踪鼠标的位置并且显示,其内又内嵌 了Cat组件。
MouseTracker组件使用组件MouseWithCat,实现功能。
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 }} />
);
}
}
class MouseWithCat 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: '100vh' }} onMouseMove={this.handleMouseMove}>
{/*
在这里,我们可以简单地使用 <Cat> 来替换 <p>。但是如果这样
做的话,当我们每次遇到这样的情况时,就需要创建一个单独的
<MouseWithSomethingElse>。所以 <MouseWithCat> 并不是真正的可复用组件。
*/}
<Cat mouse={this.state} />
</div>
);
}
}
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>移动鼠标!</h1>
<MouseWithCat />
</div>
);
}
但是此时假如有一个Dog的组件,为了实现能够实时显示MouseWithDog,此时就得将MouseWithCat代码重新写一个一样的,只是其中内嵌【】。这样的代码显然比较臃肿。
Props
不必要将Cat写死在MouseWithXXX组件中,即相当于给其挖个槽出来,想放什么通过props属性即可。
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 }} />
);
}
}
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: '100vh' }} onMouseMove={this.handleMouseMove}>
{/*
使用 `render`prop 动态决定要渲染的内容,
而不是给出一个 <Mouse> 渲染结果的静态表示
*/}
{this.props.render(this.state)}
</div>
);
}
}
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>移动鼠标!</h1>
//实际上这个属相叫啥都行,不一定是render,只不过这样更清晰
<Mouse render={mouse => (
<Cat mouse={mouse} />
)}/>
</div>
);
}
}
注意:
我们知道,当组件继承自PureComponent 时,此时只有当组件的state或者props数据发生改变时才重新render,常用这种方法提高渲染效率。
但是, 如果你在 render 方法里创建函数,那么使用 render prop 会抵消使用 React.PureComponent
带来的优势。因为浅比较 props 的时候总会得到 false,并且在这种情况下每一个 render
对于 render prop 将会生成一个新的值。
比如:
在这样例子中,每次
渲染,它会生成一个新的函数作为
的 prop,因而在同时也抵消了继承自React.PureComponent
的 PureComponment组件的效果!
class Mouse extends React.PureComponent {
// 与上面相同的代码......
}
class MouseTracker extends React.Component {
render() {
return (
<div>
<h1>Move the mouse around!</h1>
{/*
这是不好的!
每个渲染的 `render` prop的值将会是不同的。
*/}
<Mouse render={mouse => (
<Cat mouse={mouse} />
)}/>
</div>
);
}
}
为了解决这个问题, 可以定义一个 prop 作为实例方法,类似这样:
class MouseTracker extends React.Component {
// 定义为实例方法,`this.renderTheCat`始终
// 当我们在渲染中使用它时,它指的是相同的函数
renderTheCat(mouse) {
return <Cat mouse={mouse} />;
}
render() {
return (
<div>
<h1>Move the mouse around!</h1>
<Mouse render={this.renderTheCat} />
</div>
);
}
}