【问题标题】:Can I use a higher order component to add an onClick to my component without adding a wrapper DOM element?我可以在不添加包装 DOM 元素的情况下使用更高阶的组件向我的组件添加 onClick 吗?
【发布时间】:2018-03-20 13:07:27
【问题描述】:

我们正在将用于特定触摸屏的现有应用程序迁移到 React。屏幕有一些敏感问题,所以我们想要自定义所有可点击组件(如按钮等)的onClick 行为。例如,如果用户按下按钮然后将手指移出,我们希望onClick 也触发放手前的按钮。

一般来说,我们需要为所有的可点击对象添加一些状态,我认为Higher Order Component 是最理想的,所以我做了以下操作:

HOC

const withTouchable = WrappedComponent => {
    return class Touchable extends React.Component {
        onClick() {
            this.props.onClick();
        }

        onMouseLeave() {
            // Some complicated logic to determine if we want to fire onClick
            if(...) {
                this.props.onClick();
            }
        }

        // Other mouse and touch handlers
        // onMouseMove = ...

        render() {
            return (
                <WrappedComponent
                    {...this.props}

                    onClick={this.onClick.bind(this)}
                    onMouseLeave={this.onMouseLeave.bind(this)}

                    // other mouse and touch handlers
                />
            );
        }
    };
};

我们希望可点击的示例组件。

const Heading = ({ title }) => <h1>{title}</h1>;

示例应用

const TouchableHeading = withTouchable(Heading);

class App extends React.Component {

    onClick() {
        console.log("title tapped")
    }

    render() {
        return (
            <TouchableHeading
                title="Some title"
                onClick={this.onClick.bind(this)}
            />
        );
    }
}

ReactDOM.render(<App />, document.getElementById("root"));

不幸的是,这不起作用,因为虽然&lt;WrappedComponent&gt; 是通过鼠标和触摸处理程序返回的,但&lt;Heading&gt; 并没有使用它。见codepen.io/bvgZwb

另一种方法是在 WrapperComponent 周围包裹一个 div:

render() {
    return (
        <div
            onClick={this.onClick.bind(this)}
            onMouseLeave={this.onMouseLeave.bind(this)}
            // other mouse and touch handlers
        >
            <WrappedComponent {...this.props}/>
        </div>
    );
}

codepen.io/xWgBMJ。但这增加了一个额外的 DOM 元素,这并不理想(它与样式混淆,没有时间重写整个应用程序)。

还有其他我没有考虑过的方法来实现这一目标吗?我确实研究了render props and using functions as children,但我认为不可能以这种方式实现我的目标。

注意:不要介意this.onClick.bind(this)I know

【问题讨论】:

    标签: javascript reactjs onclick higher-order-components


    【解决方案1】:

    不使用包装器并做你想做的事情的唯一方法是使用休息道具,比如

    const Heading = ({ title, ...rest }) =&gt; &lt;h1 {...rest}&gt;{title}&lt;/h1&gt;;

    但是,如果您对此不小心,您的所有属性都会到达您的 DOM,因为 React 在最新版本中不再进行属性验证

    make 专门为 Heading 添加事件属性

    const Heading = ({ title, onClick, onMouseLeave }) => (
         <h1 
            onClick={onClick}
            onMouseLeave={onMouseLeave}
         >
           {title}
         </h1>
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多