我正在尝试使用reactjs创建一个可定制的通用可扩展模式。我知道这里有很多图书馆,但是我只是为了理解反应生态系统而发展。但是,在我的模态中,当我在模态内容中单击时,模态会关闭。仅当单击关闭按钮且位于模态区域之外时,模态才应关闭。
这就是我所做的。演示也在那里
https://codepen.io/anon/pen/mzMdoq
代码
class Portal extends React.Component {
render() {
return ReactDOM.createPortal(
<div
style={{
position: "absolute",
top: "0",
bottom: "0",
left: "0",
right: "0",
display: "grid",
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0,0,0,0.3)"
}}
onClick={this.props.onClose}
>
<div
style={{
padding: 20,
background: "#fff",
borderRadius: "2px",
display: "inline-block",
minHeight: "300px",
margin: "1rem",
position: "relative",
minWidth: "300px",
boxShadow: "0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)",
justifySelf: "center"
}}
>
{this.props.children}
<hr />
<button onClick={this.props.onClose}>Close</button>
</div>
</div>,
document.body
);
}
}
class Modal extends React.Component {
modalRef = React.createRef();
componentDidMount() {
document.addEventListener("mousedown", this.handleClick, false);
}
componentWillUnmount() {
document.removeEventListener("mousedown", this.handleClick, false);
}
handleClick = e => {
const node = this.modalRef.current;
console.log("props", node);
if (
this.modalRef &&
this.modalRef.current &&
this.modalRef.current.contains(e.target)
) {
return;
} else {
this.props.onClose();
}
};
render() {
return (
<React.Fragment>
<Portal {...this.props} ref={this.modalRef} />
</React.Fragment>
);
}
}
class ModalExample extends React.Component {
state = { showModal: false };
showModal = () => this.setState({ showModal: true });
handleClose = () => this.setState({ showModal: false });
render() {
const { showModal } = this.state;
return (
<React.Fragment>
<button onClick={this.showModal}>Modal</button>
{showModal ? (
<Modal showModal={showModal} onClose={this.handleClose}>
This is the modal content!
</Modal>
) : null}
</React.Fragment>
);
}
}
function App() {
return (
<div className="App">
<h1>Hello</h1>
<ModalExample />
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
答案 0 :(得分:0)
您应该删除onClick={this.props.onClose}
内的ReactDOM.createPortal
,它将正常工作
答案 1 :(得分:0)
将e.stopPropagation()添加到模态主体的onClick。像这样
<div
style={{
padding: 20,
background: "#fff",
borderRadius: "2px",
display: "inline-block",
minHeight: "300px",
margin: "1rem",
position: "relative",
minWidth: "300px",
boxShadow: "0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)",
justifySelf: "center"
}}
onClick={e => e.stopPropagation()}
>
{this.props.children}
<hr />
<button onClick={this.props.onClose}>Close</button>
</div>
答案 2 :(得分:0)
嗯,这不完全是一个答案,但是如果有帮助的话……
我通常以这种方式生成模态
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_modal
在这里,您可以看到DOM中已经存在模态,并且使用js可以根据需要将其隐藏或显示。 div已存在,因此与您的有所不同。
答案 3 :(得分:0)
您的覆盖div包装了模式内容div,因此,点击内容也被视为点击了覆盖。
解决此问题的一种方法是不将模式内容嵌套在叠加层中,而是将其移动到外部:
return ReactDOM.createPortal(
<div style={{
position: "absolute",
top: "0",
bottom: "0",
left: "0",
right: "0",
display: "grid",
justifyContent: "center",
alignItems: "center"
}}>
<div
style={{
position: "absolute",
top: "0",
bottom: "0",
left: "0",
right: "0",
display: "grid",
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0,0,0,0.3)"
}} onClick={this.props.onClose}
/>
<div
style={{
padding: 20,
background: "#fff",
borderRadius: "2px",
display: "inline-block",
minHeight: "300px",
margin: "1rem",
position: "relative",
minWidth: "300px",
boxShadow: "0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)",
justifySelf: "center"
}}
>
{this.props.children}
<hr />
<button onClick={this.props.onClose}>Close</button>
</div>
</div>,
document.body
);