gpt4 book ai didi

reactjs - 为什么底层组件重新渲染时popper会跳到左上角?

转载 作者:行者123 更新时间:2023-12-04 08:57:17 25 4
gpt4 key购买 nike

我正在使用 Material-UI Popper 组件(它又使用 popper.js)来创建一个悬停工具栏。在大多数情况下,它运行良好,除了一个奇怪的行为:

  • 选择一些文本:悬停工具栏出现在文本上方 - 正如预期的那样。
  • 选择工具栏中的任意按钮:执行相应的操作。但是工具栏会跳转到窗口的左上角。见下文。

  • enter image description here
    您可以在 my Storybook 中尝试此行为- 只需选择一些文本并单击“T”按钮之一。
    基本问题集中在 popper 的定位上:
  • 当用户选择一些文本时,会创建一个假虚拟元素并将其作为 anchor 元素传递给 popper。波普尔使用这个 anchorEl定位悬停工具栏。到现在为止还挺好。
  • 当用户单击工具栏中的按钮时,悬停的工具栏会跳转到窗口的左上角。

  • 我猜这是因为当底层组件重新渲染时 anchor 元素以某种方式丢失了。我不知道为什么,但这只是我的理论。有人可以帮我解决这个问题吗?
    计算 anchorEl 的代码位于 React 内 useEffect() .我已确定 useEffect 的依赖项列表是准确的。我可以看到,当工具栏跳转时, useEffect()没有被调用,这意味着 anchorEl没有被重新计算。这让我相信工具栏应该保持其当前位置不变,而不是跳到 (0,0)。但这并没有发生:-(。
    这是 useEffect()工具栏组件内的代码。您可以在 my repo 中找到完整代码.任何帮助将非常感激。
    useEffect(() => {
    if (editMode === 'toolbar') {
    if (isTextSelected) {
    const domSelection = window.getSelection();
    if (domSelection === null || domSelection.rangeCount === 0) {
    return;
    }
    const domRange = domSelection.getRangeAt(0);
    const rect = domRange.getBoundingClientRect();
    setAnchorEl({
    clientWidth: rect.width,
    clientHeight: rect.height,
    getBoundingClientRect: () =>
    domRange.getBoundingClientRect(),
    });
    setToolbarOpen(true);
    } else {
    setToolbarOpen(false);
    }
    } else {
    setToolbarOpen(false);
    }
    }, [editMode, isTextSelected, selection, selectionStr]);

    最佳答案

    我相信你的 domRangetoggleBlock 之后不再有效完成它的工作(由于 dom 节点被替换),所以 getBoundingClientRect不再返回任何有意义的东西。
    您应该能够通过重做获取anchorEl 的getBoundingClientRect 范围内的工作来解决此问题。 .也许类似于以下内容(我没有尝试执行它,所以不能保证没有小错误):

    const getSelectionRange = () => {
    const domSelection = window.getSelection();
    if (domSelection === null || domSelection.rangeCount === 0) {
    return null;
    }
    return domSelection.getRangeAt(0);
    };
    useEffect(() => {
    if (editMode === "toolbar") {
    if (isTextSelected) {
    const domRange = getSelectionRange();
    if (domRange === null) {
    return;
    }
    const rect = domRange.getBoundingClientRect();
    setAnchorEl({
    clientWidth: rect.width,
    clientHeight: rect.height,
    getBoundingClientRect: () => {
    const innerDomRange = getSelectionRange();
    return innerDomRange === null
    ? null
    : innerDomRange.getBoundingClientRect();
    }
    });
    setToolbarOpen(true);
    } else {
    setToolbarOpen(false);
    }
    } else {
    setToolbarOpen(false);
    }
    }, [editMode, isTextSelected, selection, selectionStr]);

    关于reactjs - 为什么底层组件重新渲染时popper会跳到左上角?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63747451/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com