是否有React
方法来创建绑定DOM事件的另一个元素的包装器组件,而不生成另一个元素(如<div>
中所述)?
E.g。
class TripleClickWrapper extends Component {
render() {
return <div onClick={::this._onClick}>{this.props.children}</div>
}
_onClick() { /* counts clicks and handles timeouts etc */ }
}
// somewhere else:
<TripleClickWrapper onTripleClick={::this._doSomething}>
<SomeComponent />
</TripleClickWrapper>
我不希望额外的<div>
TripleClickWrapper
创建,但我希望将onClick
绑定到包装器,而不将其传递给<SomeComponent>
。没有到达DOM
y(findDOMNode
+ addEventLisetener
+删除取消)的任何好方法?
如果我不需要绑定DOM事件,我可以返回React.Children.only(this.props.children)
。
答案 0 :(得分:2)
您可以在渲染函数中返回子组件的扩充/克隆版本:https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement
您可以在克隆过程中添加其他道具。
render() {
const newProps = /* any props/event handlers you want to add */;
return React.cloneElement(React.Children.only(this.props.children), newProps);
}
答案 1 :(得分:1)
基于源代码(具体来说,这一行:https://github.com/facebook/react/blob/v15.0.0-rc.2/src/renderers/dom/shared/ReactDOMComponent.js#L621)我看到一个可能的解决方案可能是注入一个EventPlugin。这是因为enqueuePutListener
被调用,而后者又调用ReactBrowserEventEmitter.listenTo
- &gt; ReactEventListener.trapBubbledEvent
- &gt;实际EventListener.listen
的{{1}}。那里的addEventListener
语句会查找插件名称。我不确定该机制是如何工作的,并且在文档中没有找到它,但是有些调查听起来像是一种可能的解决方案。例如,当300ms延迟仍然存在时,有一个插件可以处理点击事件。
答案 2 :(得分:0)
我最终采用了这种方法:
<div>
div
已经有onClick
它仍然应该运行addEventListener
上手动使用findDOMNode(this)
。理由:1)内部onClick
无法运行e.stopPropagation()
并停止我添加的事件,因为React事件在document
上运行,没有useCapture
,以及2)失去React事件系统的好东西。目前我正在使用包装器中的唯一孩子并使用cloneElement,正如@Calvin Belden推荐的那样,并将我的事件与现有事件相结合。
render() {
const onlyChild = React.Children.only(children)
const events = {
onClick: this.doSomething,
onMouseEnter: this.doSomethingElse,
// ...
}
for (let [eventName, fn] of Object.entries(events)) {
if (onlyChild.props[eventName]) {
let oldFn = onlyChild.props[eventName]
events[eventName] = e => {
oldFn(e)
if (!e.isPropagationStopped()) fn(e)
}
}
}
return React.cloneElement(onlyChild, events)
}
当我使用组件而不是div时,它仍然强迫我传递事件:<TripleClickWrapper><SomeComponent></TripleClickWrapper>
。 SomeComponent
必须将onClick传递给它的div。
不是最佳,但尽可能干净。