javascript - 我可以使用高阶组件将 onClick 添加到我的组件而不添加包装器 DOM 元素吗?

标签 javascript reactjs onclick higher-order-components

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

一般来说,我们需要为所有可点击对象添加一些状态,我想到了 Higher Order Component将是理想的选择,所以我做了以下内容:

高级组织

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"));

不幸的是,这不起作用,因为虽然 <WrappedComponent>与鼠标和触摸处理程序一起返回,<Heading> 不使用它.参见 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 .

最佳答案

不使用包装器并做你想做的唯一方法是使用像这样的休息 Prop

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

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

专门为Heading添加事件属性like

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

关于javascript - 我可以使用高阶组件将 onClick 添加到我的组件而不添加包装器 DOM 元素吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49385060/

相关文章:

javascript - 确保脚本可用性的模式或技术?

javascript - 上一张幻灯片和自动播放 Jquery slider ,

javascript - getElementById 变量 + 数字

javascript - 对象数组优化

css - 多个 onClick 事件触发

javascript - $inc 追随者数量,还是我应该使用聚合来跟踪他们?

reactjs - 如何异步/等待 redux-thunk 操作?

javascript - 为什么 React Component 渲染计数器会增加 2?

jquery - 在模态运行之前引导模态 onclick

java - Android TextView : onClick after Moving TextView