前提:页面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>
  );
});

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐