我有一个页脚组件,该组件具有切换模式组件的功能。在模态组件中,我有一个背景包装器,而模态嵌套在该包装器中。我已经将toggleModal函数设置为prop,并将其添加到模式包装器中。我不希望模态本身分配有此click函数,因此尽管似乎不起作用,但我在函数中使用了stopPropagation()
来停止事件冒泡。
页脚组件:
const Footer = () => {
const [showModal, setShowModal] = useState(false);
function toggleModal(e) {
e.stopPropagation();
setShowModal(!showModal);
}
return (
<div>
<button onClick={toggleModal}>Modal toggle</button>
<Modal show={showModal} toggle={toggleModal}>This is a modal</Modal>
</div>
)
}
模式组件:
const Modal = () => {
return (
<div className="modal__wrapper" onClick={props.toggle}>
<div className="modal p-3">
<div className="modal__close" onClick={props.toggle} role="button" aria-hidden="true">
X
</div>
{props.children}
</div>
</div>
)
}
尽管似乎不起作用,但可以阻止事件冒泡。
您是说事件冒泡不起作用,还是模态通常不起作用?我发现了两个代码问题,这些问题在修复后似乎可以使模态工作。另外,您may想要e.preventDefault()
的行为,但是我不确定您的问题。
const Modal = (props) => {
show
属性显示/隐藏模式div:props.show && <div className="modal__wrapper" onClick={props.toggle}>
要查看stopPropagation
和preventDefault
的行为差异,请尝试将此radio
添加到按钮下方。每次需要重置radio
进行实验时,都需要刷新页面。
<input type="radio" name="gender" value="male" onClick={toggleModal}/>
[preventDefault
停止设置radio
,它防止无线电组件的默认行为设置值。
stopPropagation
将不是停止设置radio
,因为它只停止冒泡到父元素的事件。在text <input>
上有用,可以防止Enter键之类的事件影响要提交的父<form>
元素(如果需要)。
我希望这有助于解决您的问题。
发生的事情:
.modal
或其中的另一个元素被单击。没有侦听器附加到该元素,因此事件继续冒泡直到祖先。.modal__wrapper
,该事件具有click事件的侦听器。侦听器不会区分哪个元素是事件的直接目标:元素本身或其后代之一。即使目标是包装器内的另一个元素,也会触发props.toggle()
。侦听器停止传播。事件停止冒泡,但是树上没有人听得更高。我建议您将引用附加到包装器,并检查事件目标是否是包装器本身。
模态组件看起来像这样:
const Modal = (props) => {
const wrapperRef = useRef();
const handleClick = e => {
if(e.target === wrapperRef.current) {
props.toggle(e);
}
};
return (
<div className="modal__wrapper" onClick={handleClick} ref={wrapperRef}>
<div className="modal p-3">
<div className="modal__close" onClick={props.toggle} role="button" aria-hidden="true">
X
</div>
{props.children}
</div>
</div>
);
};