前提:页面A是有table,table行展开有子表childTable,childTable的每个单元格可以触发提示框,提示框是用Tooltip组件封装,有专门关闭按钮。切换到B页面,触发关闭按钮无效
原因: 切换到其他页面,按道理childTable会被销毁,用了keepalive进行缓存,childTable就缓存到keepalive内。所以切换到其他页面时,react拿不到提示框,所以setState无效(可以说是被存起来了,但不会去刷新页面),但调试框Element可以拿到提示框,这个时候我们可以从dom操作出发
解决思路:
1.给每个提示框添加id,拿到提示框的dom,设置其样式为display:none就可以提前让其关闭。
由于我直接用的Tooltip组件,所以我只能在他里面的内容添加id,再找到最外层ant-tooltip的dom节点
2.在关闭后,open状态为false(切换到其他页面open状态不会发生变化,只有页面切换回来,open状态才被拿出来渲染),这个时候把它样式设置为空,防止阻碍Tooltip内置打开效果
实现代码:(效果:鼠标进入打开,鼠标出去关闭,点击会打开,但只能摁X按钮才能关闭)
const Atooltip = React.memo(({ tip, title, width, placement }) => {
const [tooltipOpen, setTooltips] = useState(false);
const [clickStatus, setClickStatus] = useState(false);
let id;
const generateUniqueId = () => {
// 这里可以根据你的需求生成唯一的 ID
id = `element_${Math.random().toString(36).substr(2, 9)}`;
return id;
};
const findClosestTooltip = elementId => {
const element = document.getElementById(elementId);
if (element) {
const closestTooltip = element.closest('.ant-tooltip');
return closestTooltip;
}
return null;
};
const destroyTooltip = () => {
try {
// 找到了最近的 .ant-tooltip 元素
const closestTooltip = findClosestTooltip(id);
if (closestTooltip) {
// 在这里可以进行隐藏dom
closestTooltip.style.display = 'none';
}
} catch (error) {
console.log(error);
}
};
useEffect(() => {
const closestTooltip = findClosestTooltip(id);
if (tooltipOpen && closestTooltip) {
closestTooltip.style = {};
}
}, [tooltipOpen]);
return (
<Tooltip
placement={placement || 'topLeft'}
overlayClassName="tableTooltip"
onMouseEnter={e => {
if (e.target.clientWidth >= e.target.scrollWidth) {
e.target.style.pointerEvents = 'none'; // 阻止鼠标事件
} else {
setTooltips(true);
}
}}
title={
<>
<div id={generateUniqueId()}>
<div className="close" style={{ cursor: 'auto' }}>
<div
style={{ float: 'right', cursor: 'pointer', padding: '0 4px' }}
onClick={e => {
e.stopPropagation();
setTooltips(false);
setClickStatus(false);
destroyTooltip();
}}
>
<CloseOutlined />
</div>
</div>
<div className="varPosTip">{tip}</div>
</div>
</>
}
onMouseLeave={() => {
// 如果触发点击事件就不要再触发鼠标离开事件,防止页面闪烁
if (!clickStatus) {
setTooltips(false);
}
}}
onClick={() => {
setClickStatus(true);
setTooltips(true);
}}
open={tooltipOpen}
>
<div
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(title) }}
style={{
display: 'inline-block',
width: width || '100%',
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
}}
></div>
</Tooltip>
);
});