1

我有一个场景,我想创建一个 HOC,当它们发生在 HOC 上时检测鼠标事件(例如mouseenter, ) ,然后传递一个特殊的道具(例如)。我通过使用回调来获取包装的组件实例,然后将事件侦听器添加到我的 HOC 中的包装实例来实现这一点。mouseleaveWrappedComponentWrappedComponentcomponentIsHoveredref

import React, { Component } from 'react'
import ReactDOM from 'react-dom'

export default (WrappedComponent) => {
	return class DetectHover extends Component {

		constructor(props) {
			super(props)
			this.handleMouseEnter = this.handleMouseEnter.bind(this)
			this.handleMouseLeave = this.handleMouseLeave.bind(this)
			this.bindListeners = this.bindListeners.bind(this)
			this.state = {componentIsHovered: false}
			this.wrappedComponent = null
		}

		componentWillUnmount() {
			if (this.wrappedComponent) {
				this.wrappedComponent.removeEventListener('mouseenter', this.handleMouseEnter)
				this.wrappedComponent.removeEventListener('mouseleave', this.handleMouseLeave)
			}
		}

		handleMouseEnter() {
			this.setState({componentIsHovered: true})
		}

		handleMouseLeave() {
			this.setState({componentIsHovered: false})
		}

		bindListeners(wrappedComponentInstance) {
			console.log('wrappedComponentInstance', wrappedComponentInstance)
			if (!wrappedComponentInstance) {
				return
			}
			this.wrappedComponent = ReactDOM.findDOMNode(wrappedComponentInstance)
			this.wrappedComponent.addEventListener('mouseenter', this.handleMouseEnter)
			this.wrappedComponent.addEventListener('mouseleave', this.handleMouseLeave)
		}


		render() {
			const props = Object.assign({}, this.props, {ref: this.bindListeners})
			return (
					<WrappedComponent 
						componentIsHovered={this.state.componentIsHovered}
						{...props} 
					/>
			)
		}
	}
}

问题是,这似乎只在WrappedComponent是 类组件时才有效 - 对于功能组件,ref总是null。我会尽快将WrappedComponent内部<div></div>标签放在我的 HOC 中并在该 div 包装器上执行事件检测,但问题是即使是普通的 div 标签也会将其设置WrappedComponent为块元素,这在我的用例中不起作用HOC 也应该适用于内联元素。任何建议表示赞赏!

4

1 回答 1

0

您可以将 css 选择器和所需的特定样式传递给高阶组件,如下所示:

import React, {Component} from 'react';

const Hoverable = (WrappedComponent, wrapperClass = '', hoveredStyle= 
    {}, unhoveredStyle={}) => {

    class HoverableComponent extends Component {
        constructor(props) {
            super(props);
            this.state = {
                hovered: false,
            }
        }

        onMouseEnter = () => {
            this.setState({hovered: true});
        };

        onMouseLeave = () => {
            this.setState({hovered: false});
        };

        render() {
            return(
                <div
                     className={wrapperClass}
                     onMouseEnter= { this.onMouseEnter }
                     onMouseLeave= { this.onMouseLeave }
                >
                    <WrappedComponent
                        {...this.props}
                        hovered={this.state.hovered}
                    />
                </div>
            );
        }

    }

    return HoverableComponent;
};

export default Hoverable;

并使用 Fragment 而不是 div 来包装您的组件:

class SomeComponent extends React.Component {
    render() {
        return(
            <Fragment>
                <h1>My content</h1>
            </Fragment>
        )
        }

然后像这样包起来

const HoverableSomeComponent = Hoverable(SomeComponent, 'css-selector');
于 2018-10-26T00:45:41.270 回答