<Mouse render={(mouse) => {}}/>
- <Mouse render={(mouse) => (
- <p>鼠标当前位置 {mouse.x},{mouse.y}p>
- )}/>
创建Mouse组件,在组件中提供复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
- class Mouse extends React.Component {
- // 鼠标位置state
- state = {
- x: 0,
- y: 0
- }
- // 鼠标移动事件的事件处理程序
- handleMouseMove = e => {
- this.setState({
- x: e.clientX,
- y: e.clientY
- })
- }
- // 监听鼠标移动事件
- componentDidMount() {
- window.addEventListener('mousemove', this.handleMouseMove)
- }
- render(){
- //这一步先写null,后面会完善
- return null
- }
- }
将要复用的状态作为 props.render(state) 方法的参数,暴露到组件外部
- render() {
- return this.props.render(this.state)
- }
-
- <Mouse render={(mouse) => {return ()}} />
使用 props.render() 的返回值作为要渲染的内容
- render={(mouse) => {
- return (
- <p>
- 鼠标位置:{mouse.x},{mouse.y}
- p>
- )
只实现了状态结构的复用,并没有实现UI结构的复用
在鼠标上加上图片,跟随鼠标一起移动
导入图片资源
import img from './images/star.png'
将图片写下以下内容
- {/* 图片 */}
- <Mouse render={mouse => {
- return <img src={img} alt="star" style={{
- position: 'absolute',
- //减64是因为图片128*128,想要鼠标在图片中心,则需要-64
- top: mouse.y - 64,
- left: mouse.x - 64
- }} />
- }}>Mouse>
- //组件内部
- render() {
- return this.props.children(this.state)
- }
-
- <Mouse>
- {mouse => {
- return (
- <p>
- 鼠标位置:{mouse.x},{mouse.y}
- p>
- )
- }}
- Mouse>
-
- <Mouse >{mouse =>
- (<img src={img} alt="star" style={{
- position: 'absolute',
- top: mouse.y - 64,
- left: mouse.x - 64
- }}
- />)
- }
- Mouse>
Context 中的用法:
- <Consumer>
- {data => <span>data参数表示接收到的数据 -- {data}span>}
- Consumer>
推荐:给 render props 模式添加 props校验
- import propTypes from 'prop-types'
-
- // 添加props校验
- Mouse.propTypes = {
- children:propTypes.func.isRequired
- }
应该在组件卸载时解除 mousemove 事件绑定
因为componentDidMount是我们自己手动开的,既然开了一个,卸载时,就要关这一个
- // 推荐:在组件卸载时移除事件绑定
- componentWillUnmount(){
- window.addEventListener('mousemove',this.handleMouseMove)
- }
- class Mouse extends React.Component {
- render() {
- return <WrappedComponent {...this.state} />
- }
- }
const EnhancedComponent = withHOC(WrappedComponent)
创建一个函数,名称约定以 with 开头
function withMouse() {}
指定函数参数,参数应该以大写字母开头(作为要渲染的组件)
function withMouse(WrappedComponent) {}
在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
- function withMouse(WrappedComponent) {
- class Mouse extends React.Component {。。。}
- return Mouse
- }
在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件
UI组件由WrappedComponent提供
- // Mouse组件的render方法中:
- //Mouse组件的状态->...this.state
- return <WrappedComponent {...this.state} />
调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
- //Positon组件作为参数传进来
- // 创建组件
- const MousePosition = withMouse(Position)
- // 渲染组件
- <MousePosition />
导入图片
import img from './images/star.png'
图片的组件
- const Star = props =>(
- <img src={img} alt="" style={{
- position:"absolute",
- top:props.y -64,
- left:props.x -64
- }} />
- )
让图片跟随鼠标移动
- //调用高阶组件来增强图片的组件
- const MouseStar = withMouse(Star)
-
- {/* 渲染增强后的组件 */}
- <MouseStar>MouseStar>
完整代码
- // 创建高阶组件
- function withMouse(WrappedComponent) {
- // 该组件提供复用的状态逻辑
- class Mouse extends React.Component {
- // 鼠标状态
- state = {
- x: 0,
- y: 0
- }
- // 更新状态逻辑
- handleMouseMove = e => {
- this.setState({
- x: e.clientX,
- y: e.clientY
- })
- }
- // 控制鼠标状态的逻辑
- componentDidMount() {
- window.addEventListener('mousemove', this.handleMouseMove)
- }
-
- //在组件卸载时移除事件绑定
- componentWillUnmount() {
- window.addEventListener('mousemove', this.handleMouseMove)
- }
- render() {
- return <WrappedComponent {...this.state}>WrappedComponent>
- }
- }
- return Mouse
- }
-
- // 用来测试高阶组件
- const Position = props => (
- <p>
- 鼠标当前位置:(x:{props.x},y:{props.y})
- p>
- )
-
- // 获取增强后的组件
- const MousePosition = withMouse(Position)
-
- class App extends React.Component {
- render() {
- return (
- <div>
- <h1>高阶组件h1>
- {/* 渲染增强后的组件 */}
- <MousePosition>MousePosition>
- div>
- )
- }
- }
- //放在创建高阶组件内部
- Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
-
- 设置 getDisplayName()
- function getDisplayName(WrappedComponent) {
- return WrappedComponent.displayName || WrappedComponent.name || 'Component'
- }
由上图变成下图:

<WrappedComponent {...this.state} {...this.props} />