我已经在我的应用程序内部创建了一个react门户来处理Modal的使用。门户网站目标是我的根元素的兄弟姐妹,位于我的React root div之外。
<html>
<body>
<div id="root">{{app.html}}</div>
<div id="modal-root">
<div class="modal" tabIndex="-1" id="modal-inner-root" role="dialog">
</div>
</div>
</body>
</html>
因此,我的Portal内容呈现在react应用程序之外,并且工作正常。这是我的反应门户代码
const PortalRawModal = (props) => {
const [ display, setDisplay ] = useState(document.getElementById("modal-inner-root").style.display)
const div = useRef(document.createElement('div'))
useEffect(()=> {
const modalInnerRoot = document.getElementById("modal-inner-root")
if(validate(props.showModalId)) {
if( props.showModalId == props.modalId && _.size(props.children) > 0 ) {
setDisplay("block");
if(_.size(modalInnerRoot.childNodes) > 0) {
modalInnerRoot.replaceChild(div.current,modalInnerRoot.childNodes[0]);
} else {
modalInnerRoot.appendChild(div.current);
}
div.current.className = props.modalInner;
document.getElementById("modal-root").className = props.modalClassName;
document.body.className = "modal-open";
} else {
document.getElementById("modal-root").className = props.modalClassName;
if(div.current.parentNode == modalInnerRoot) {
modalInnerRoot.removeChild(div.current);
div.current.className = "";
}
}
} else {
setDisplay("none");
document.getElementById("modal-root").className = "";
if(div.current.parentNode == modalInnerRoot) {
modalInnerRoot.removeChild(div.current).className = "";
}
document.body.className = "";
}
},[ props.showModalId ])
useEffect(()=> {
document.body.className = display == "none" ? "" : "modal-open";
document.getElementById("modal-inner-root").style.display = display;
return () => {
if(!validate(props.showModalId)) {
document.body.className = "";
document.getElementById("modal-inner-root").style.display = "none"
}
};
},[ display])
useEffect(()=> {
if(_.size(props.children) <= 0){
modalInnerRoot.removeChild(div.current)
document.body.className = "";
document.getElementById("modal-inner-root").style.display = "none";
}
return () => {
if(_.size(props.children) <= 0){
modalInnerRoot.removeChild(div.current)
document.body.className = "";
document.getElementById("modal-inner-root").style.display = "none";
}
}
},[props.children, props.showModalId])
return ReactDOM.createPortal(props.children ,div.current);
}
每当通过子代并安装模态时,重绘的DOM几乎不会延迟。但是相同的标记需要花费时间,甚至会使浏览器标签崩溃。在处理繁重的DOM操作时,我哪里出错了?还是有async
种方法来处理繁重的DOM操作而不会影响整体性能?
答案 0 :(得分:0)
原因因素可以归因于此:
props.children
是一个对象,因此每次重新渲染都将始终运行最后一个效果,因此,即使再次传递相同的子代,它也将是一个新对象。一个地方是:
if (_.size(props.children) <= 0) {
modalInnerRoot.removeChild(div.current);
}
可以在渲染函数中替换,例如:
{React.Children.count(props.children) ? <div /> : null}