https://blog.csdn.net/sd19871122/article/details/97612107
createProtal
改造 Modal 組件
在 html 中除了 div#root
之外,給 Modal 預留了一個新的 div#modal-root
,:
-
const appRoot = document.getElementById('root');
-
const modalRoot = document.getElementById('modal-root');
改造 Modal 容器
新的 Modal 容器組件內容如下:
class ModalContainer extends Component {
constructor(props) {super(props);
this.el = document.createElement('div');}
componentDidMount()
{modalRoot.appendChild(this.el);}
componentWillUnmount()
{modalRoot.removeChild(this.el);}
render() {return ReactDOM.createPortal(this.props.children,this.el);}}
將 ModalContent 掛載到 ModalContainer
class App2 extends Component {
state = {
name: 'clickme'
}
componentDidMount(){
// console.log(findDOMNode(ref.current))
}
clickHandle = () => {
this.setState({
name: 'clickme' + Date.now()
});
}
render() {
return (
<div className="App">
<ModalContainer>
<ModalContent />
</ModalContainer>
</div>);
}}
創建一個Foo組件(表現為200*200的div),放到body的中央位置。
import React from "react";
import ReactDom from "react-dom";
export default class extends React.Component {
div = document.createElement("div");
componentWillUnmount() {
document.body.removeChild(this.div);
}
componentDidMount() {
document.body.appendChild(this.div);
}
render() {
return ReactDom.createPortal(<Foo />, this.div);
}
}
const styles = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 200,
height: 200,
zIndex: 100,
background: "rgba(222,222,222,0.4)",
boxShadow: "5px 5px 5px 5px gray"
};
const Foo = () => {
return <div style={styles}>Portals的使用</div>;
};
Portals的事件傳遞
import React from "react";
import ReactDom from "react-dom";
class App extends React.Component {
div = document.createElement("div");
componentWillUnmount() {
document.body.removeChild(this.div);
}
componentDidMount() {
document.body.appendChild(this.div);
}
render() {
return ReactDom.createPortal(<Foo />, this.div);
}
}
const styles = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 200,
height: 200,
zIndex: 100,
background: "rgba(222,222,222,0.4)",
boxShadow: "5px 5px 5px 5px gray"
};
const Foo = () => {
return (
<div onClick={() => console.info("觸發點擊事件")} style={styles}>
Portals的使用
</div>
);
};
export default () => (
<div
style={{ border: "1px solid red" }}
onClick={() => console.info("點擊事件冒泡到其React的虛擬DOM父節點")}
>
<p>React虛擬DOM父節點</p>
<App />
</div>
);
事件的傳遞有效,在Foo組件觸發的click事件,依然會傳遞到App組件