React:冒泡嵌套组件上的点击事件
React: Bubbling up click events on nested components
我正在创建一个 React 文件树,并将树设置为 React 组件。树可以采用 contents
属性,它是字符串数组或其他 <Tree />
组件(这启用嵌套文件结构 UI)。这些树组件可以无限嵌套。
我需要在嵌套树组件的子组件上注册一个点击事件,但我无法让它在第一层嵌套之外工作。我正在处理的一个简化示例:
//In App - the top level component
const App = React.createClass({
_handleChildClick () {
console.log("this is where all child clicks should be handled");
},
render () {
return (
<Tree
handleChildClick={this._handleChildClick}
contents={[
<Tree />
]}
/>
);
}
});
//And in the tree component
<div onClick={this.props.handleChildClick}></div>
If you want to see more detail - here's the github repo.
我尝试研究这个问题并看到人们使用 {...this.props}
但我不确定这是否适用于我的场景 - 如果适用,我无法让它工作。
感谢您对此提供的任何帮助。
点击处理在第一级之后不起作用的原因是因为你的第二级树组件(内容数组中的那个)没有得到适当的道具 handleChildClick
传入。(顺便说一句,我认为惯例是调用 prop onChildClick
而处理程序函数被调用 handleChildClick
- 但我离题了。)
我的理解是否正确,您实际上想要通知从单击的组件到顶部的每一层?为此,您需要扩展 contents 数组中树组件的属性——它需要接收其父组件的点击处理程序。当然这个不能静态的写下来,需要动态的写:
您的 Tree 组件,在实际呈现其子组件之前,应该使用组件的点击处理程序扩展它们中的每一个,这可以使用函数 React.cloneElement
完成(参见 API documentation and a more detailed discussion)。直接将它应用到您的组件会使事情变得有点混乱,因为您在 prop 中传递组件的子项,所以您需要弄清楚要修改哪个 prop。稍微不同的布局会在这里对您有很大帮助:
<Tree handleChildClick={this._handleChildClick}>
<Tree />
</Tree>
恕我直言,看起来更好,结构也更清晰。可以通过this.props.children访问内部组件,cloneElement使用起来会简单很多。
因此,在您的 Tree 组件中,您可以使用这样的渲染方法:
render () {
const newChildren = this.props.children.map(child =>
React.cloneElement(child, {onChildClick: this._handleChildClick}));
return (
<div>{newChildren}</div>
);
}
请注意,如果您混合使用字符串和 Tree
组件,此代码将不起作用,因此我的第三个也是最后一个建议是将这些字符串包装到一个非常薄的组件中,以便于处理.或者,您当然可以在地图内部进行类型比较。
我正在创建一个 React 文件树,并将树设置为 React 组件。树可以采用 contents
属性,它是字符串数组或其他 <Tree />
组件(这启用嵌套文件结构 UI)。这些树组件可以无限嵌套。
我需要在嵌套树组件的子组件上注册一个点击事件,但我无法让它在第一层嵌套之外工作。我正在处理的一个简化示例:
//In App - the top level component
const App = React.createClass({
_handleChildClick () {
console.log("this is where all child clicks should be handled");
},
render () {
return (
<Tree
handleChildClick={this._handleChildClick}
contents={[
<Tree />
]}
/>
);
}
});
//And in the tree component
<div onClick={this.props.handleChildClick}></div>
If you want to see more detail - here's the github repo.
我尝试研究这个问题并看到人们使用 {...this.props}
但我不确定这是否适用于我的场景 - 如果适用,我无法让它工作。
感谢您对此提供的任何帮助。
点击处理在第一级之后不起作用的原因是因为你的第二级树组件(内容数组中的那个)没有得到适当的道具 handleChildClick
传入。(顺便说一句,我认为惯例是调用 prop onChildClick
而处理程序函数被调用 handleChildClick
- 但我离题了。)
我的理解是否正确,您实际上想要通知从单击的组件到顶部的每一层?为此,您需要扩展 contents 数组中树组件的属性——它需要接收其父组件的点击处理程序。当然这个不能静态的写下来,需要动态的写:
您的 Tree 组件,在实际呈现其子组件之前,应该使用组件的点击处理程序扩展它们中的每一个,这可以使用函数 React.cloneElement
完成(参见 API documentation and a more detailed discussion)。直接将它应用到您的组件会使事情变得有点混乱,因为您在 prop 中传递组件的子项,所以您需要弄清楚要修改哪个 prop。稍微不同的布局会在这里对您有很大帮助:
<Tree handleChildClick={this._handleChildClick}>
<Tree />
</Tree>
恕我直言,看起来更好,结构也更清晰。可以通过this.props.children访问内部组件,cloneElement使用起来会简单很多。
因此,在您的 Tree 组件中,您可以使用这样的渲染方法:
render () {
const newChildren = this.props.children.map(child =>
React.cloneElement(child, {onChildClick: this._handleChildClick}));
return (
<div>{newChildren}</div>
);
}
请注意,如果您混合使用字符串和 Tree
组件,此代码将不起作用,因此我的第三个也是最后一个建议是将这些字符串包装到一个非常薄的组件中,以便于处理.或者,您当然可以在地图内部进行类型比较。