我们正在将特定触摸屏的现有应用程序移动到 React。屏幕有一些灵敏度问题,因此我们希望自定义所有可点击组件(如按钮等)的onClick
行为。例如,我们希望如果用户按下按钮,然后在松开按钮之前将手指移出按钮,则onClick
也会触发。
一般来说,我们需要为所有可点击量添加一些状态,我认为高阶组件是理想的选择,所以我做了以下工作:
组
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
另一种方法是在包装组件周围包装一个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 元素,这并不理想(它弄乱了样式,没有时间重写整个应用程序)。
有没有另一种我没有考虑过的方法来实现这一点?我确实在孩提时代研究过渲染道具和使用功能,但我认为以这种方式不可能实现我的目标。
注意:不介意this.onClick.bind(this)
,我知道。
不使用包装器并做你想做的事的唯一方法是使用休息道具,例如
const Heading = ({ title, ...rest }) => <h1 {...rest}>{title}</h1>;
但是,如果您不小心,您的所有属性都将到达您的 DOM,因为 React 不再在最新版本中进行属性验证
或
专门将事件属性添加到标题中,例如
const Heading = ({ title, onClick, onMouseLeave }) => (
<h1
onClick={onClick}
onMouseLeave={onMouseLeave}
>
{title}
</h1>
)