React组件复用
React组件复用的方式有两种:
1.render Props模式
2.高阶组件HOC
上面说的这两种方式并不是新的APi。
而是利用Raect自身的编码特点,演化而来的固定编码写法。
什么是render Props模式
1.把prop是一个函数并且要告诉组件要渲染什么内容的技术,叫做render Props模式。
2.注意的是:并不是该模式叫做render Props就必须使用名为render的props,
实际上可以使用任意的props。
对上面者一句话的详细说明:
子组件向父组件抛出数据的时候使用的是:
this.props.render(数据)中render可以是其他名,如果GiveFather.
render Props的简单使用
现在我们有一个有的需求。
光标放在屏幕上,时时获取当前坐标的位置。
请封装为一个组件。
MoveCom.js 时时获取当前坐标的位置
import React from 'react';
class MoveCom extends React.Component{
state = {
x: 0,
y:0,
}
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove',this.moveHandler)
}
render() {
return this.props.render(this.state)
}
}
export default MoveCom
父组件展示位置
import React from 'react';
import ReactDOM from 'react-dom';
import ClassCom from "./components/ClassCom"
import MoveCom from './components/MoveCom'
class Father extends React.Component{
render() {
return (
<div>
<h2> render Props的简单使用</h2>
{ /* 接受子组件向上抛出来的数据*/}
<MoveCom render={sonGiveData => {
return (
<p>当前鼠标的坐标横坐标: {sonGiveData.x } 纵坐标: {sonGiveData.y }</p>
)
}}></MoveCom>
</div>
)
}
}
ReactDOM.render(
<Father></Father>,
document.getElementById('root')
)
总结
1. 如何将子组件中的数据抛出去
render() {
return this.props.render(数据)
}
父组件接受数据
<MoveCom render={sonGiveData => {
return (
<p>当前鼠标的坐标横坐标: {sonGiveData } </p>
)
}}></MoveCom>
我们发现上面这个组件只实现了状态。
并没有实现UI结构的渲染。
UI结构的渲染是交给render函数来决定返回的内容。
小技巧:在React中 left,right,top,bottom是不需要加上px的。
<p style={{ position:'absolute', left:100, top:200 }}> 不需要加上px的 </p>
this.props.render(数据) 可以将数据传递出去
再次说明:上面这个render这个不一定非要叫做render。
只是这样写render了,你页可以叫做Aa,接受的时候使用也用Aa接收。
其实推荐children去代替render。因为这样更加语义化一些的。
在实际写的过程中也是用children。
下面我们来将代码更改一下,children去代替render。
children去代替render语法上的变化
1.使用render子组件向上抛出数据:
this.props.render(数据)
1.使用children子组件向上抛出数据:
this.props.children(数据)
在向上抛出数据的时候,只是render变为了children。
2.render接受数据:
<MoveCom render={sonGiveData => {
return (
<p>当前鼠标的坐标横坐标: {sonGiveData } </p>
)
}}></MoveCom>
2.children接收数据:
<MoveCom>
{
(data) => {
return (
<p style={{ position:'absolute', left:data.x, top:data.y }}>
横坐标: {data.x } 纵坐标: {data.y }
</p>
)
}
}
</MoveCom>
render接收数据的时候,数据是写在组件上
children接收的时候,将数据写在了里面。
render Props中使用 children去代替render
子组件
import React from 'react';
class MoveCom extends React.Component{
state = {
x: 0,
y:0,
}
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove',this.moveHandler)
}
render() {
return this.props.children(this.state)
}
}
export default MoveCom
父组件
import React from 'react';
import ReactDOM from 'react-dom';
import ClassCom from "./components/ClassCom"
import MoveCom from './components/MoveCom'
class Father extends React.Component{
render() {
return (
<div>
<h2> render Props的简单使用</h2>
<MoveCom>
{
(data) => {
return (
<p style={{ position:'absolute', left:data.x, top:data.y }}>
横坐标: {data.x } 纵坐标: {data.y }
</p>
)
}
}
</MoveCom>
</div>
)
}
}
ReactDOM.render(
<Father></Father>,
document.getElementById('root')
)
优化React中render Props模式
1.推荐给render Props添加一个校验。
因为render Props接收的是一个函数并且是必须写的。
MoveCom.propTypes = {
children: PropTypes.func.isRequired
}
2.移出事件绑定
componentWillUnmount() {
window.removeEventListener('mousemove',this.moveHandler)
}
3.这里为什么要移出事件绑定
而我们在页面中用onClick绑定的事件不需要被移除呢?
因为onClick是借用react来完成的事件绑定,react会自动帮我们移除。
这里我们不是借用React来完成的事件绑定,因此我们应该手动移除
子组件优化后的代码
import React from 'react';
import PropTypes from 'prop-types'
class MoveCom extends React.Component{
state = {
x: 0,
y:0,
}
moveHandler = e => {
this.setState({
x: e.clientX,
y:e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove',this.moveHandler)
}
componentWillUnmount() {
window.removeEventListener('mousemove',this.moveHandler)
}
render() {
return this.props.children(this.state)
}
}
MoveCom.propTypes = {
children: PropTypes.func.isRequired
}
export default MoveCom