有一个弹窗多个地方调用,期望点击按钮的时候弹出,控制显示的变量、点击事件,也不想写在父组件中,避免多个地方重复定义
冒泡机制
首先想到的是在子组件内部使用元素div
包裹,通过click
事件的冒泡机制来完成
子组件 RemarkDialog
<div onClick={() => setVisible(true)}>
{children}
<Dialog title='标题' visible={visible}>
弹窗内容
</Rydialog>
</div>
父组件
<RemarkDialog>
<Button/>
</RemarkDialog>
这是可以实现的,但是会在子组件外层包裹一层div
,这样对布局不是很友好,尝试引入父组件的className
或者使用span
替换div
,但是都没有打到逾期效果。
这个时候就要想办法拦截子组件的onClick
事件了
React.Children.map & Reatc.cloneElement
可用通过React.Children获取所以子组件,通过React.cloneElement覆盖onClick事件达到拦截效果
子组件 RemarkDialog
const newChildren = React.Children.map(children, (child) => {
return React.cloneElement(child, {
onClick: (...params) => {
setVisible(true)
child.props.onClick && child.props.onClick(...params)
}
})
})
<React.Fragment>
{newChildren }
<Dialog title='标题' visible={visible}>
弹窗内容
</Rydialog>
</React.Fragment>
父组件
<RemarkDialog>
<Button/>
</RemarkDialog>
通过React.Fragment
虚拟一个节点,但不需要监听这个节点的事件,同时还能保留子组件原来的事件,即使是非冒泡事件也可以拦截,两个事件之间互不影响,也不会影响父组件的页面布局
网友评论