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() {
// DOM已经渲染完成了;可以进行DOM操作
window.addEventListener('mousemove',this.moveHandler)
}
render() {
// 将组件中的数据暴露出去this.props.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 (
<!-- 渲染的html以及数据 -->
<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() {
// DOM已经渲染完成了;可以进行DOM操作
window.addEventListener('mousemove',this.moveHandler)
}
render() {
// 将子组件中的数据暴露出去,render变为了children
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
children: PropTypes.func.isRequired
// render: PropTypes.func.isRequired 如果使用使用的render
} 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() {
// DOM已经渲染完成了;可以进行DOM操作
window.addEventListener('mousemove',this.moveHandler)
} // 组件即将卸载的时候,移出事件监听-优化的地方
componentWillUnmount() {
window.removeEventListener('mousemove',this.moveHandler)
}
render() {
// 将子组件中的数据暴露出去,render变为了children
return this.props.children(this.state)
}
} // 规则校验-优化的地方
MoveCom.propTypes = {
// 如果是使用的children
children: PropTypes.func.isRequired
// render: PropTypes.func.isRequired 如果使用使用的render
} export default MoveCom

最新文章

  1. MySql安装出现问题---无服务,修改密码
  2. Visual Studio与Chrome调试工具使用技巧
  3. MVVMLight Messenging
  4. VC6.0和VS2010转换时经常遇到的问题
  5. 使用eBay API基本步骤介绍
  6. Go语言项目的错误和异常管理 via 达达
  7. 关于Fragment与Fragment、Activity通信的四种方式
  8. 线性回顾-generalize issue
  9. fdm_search_info_w_book_chain
  10. hdu 2159
  11. python之路--day6--字符编码
  12. [USACO09DEC]牛收费路径Cow Toll Paths
  13. WPF:在DataTemplate中使用DataType
  14. shell编程学习笔记(十二):Shell中的break/continue跳出循环
  15. 从Linux内核中获取真随机数【转】
  16. python分布式爬虫打造搜索引擎--------scrapy实现
  17. 涉及到【分页】的table的请求模式
  18. SpringBoot实战(一)之构建RestFul风格
  19. oracle的between用来判断时间区间
  20. PostgreSQL数据库资料(转)

热门文章

  1. 基于File NIO写的一个文件新增内容监控器
  2. i.MX rt 系列微控制器的学习记录
  3. 【FAQ】HMS Core推送服务与本地创建通知消息如何相互覆盖?
  4. 异步请求与中断 ( XHR,Axios,Fetch对比 )
  5. jQuery与JavaScript与Ajax三者的区别与联系
  6. 2.4 小白必看:零基础安装Linux系统(超级详细)
  7. Centos 7.4_64位系统安装指南
  8. 扩展.Net Core Identity Server 授权方式,实现 手机号+ 验证码 登录
  9. 在SpringBoot中使用logback优化异常堆栈的输出
  10. 使用VPLS跨地域多站点建立二层交换网络