我正在使用react、vite、typescript 构建一个浏览器扩展。该扩展程序具有侧面板和全屏选项卡。 仅在全屏选项卡上,我需要创建一个仅在侧面板关闭时才出现的按钮/图标。因此,当我打开侧面板时,它会隐藏该按钮,当我关闭侧面板时,它会显示该按钮。我找到了一种使用此代码检查侧面板是否关闭或打开的方法。
const contexts: chrome.runtime.ExtensionContext[] = await chrome.runtime.getContexts({ contextTypes: ["SIDE_PANEL"] });
如果
contexts.length > 0
表示侧面板打开,否则表示侧面板关闭。我在 useEffect
钩子中添加了这个逻辑,并且效果很好。问题是我需要在每次侧面板打开或关闭时再次运行此代码,以便它可以检查侧面板状态并在需要时显示/隐藏它。我尝试使用焦点和模糊事件,但不幸的是它在 Chrome 浏览器中不起作用,尽管它在 Edge 中起作用。我想到了一个想法,我可以使用 chrome.runtime.sendMessage
来触发代码并再次运行函数。在我的主要组件 index.tsx
中的 useEffect
中,我可以发送消息,它将触发代码并隐藏按钮。但是,当侧面板关闭时,我需要发送相同的消息。我尝试在 useEffect
返回函数中执行此操作,但它对我不起作用。
侧面板关闭时有什么方法可以sendMessage
吗?或者也许有更好的选择来实现显示和隐藏图标的逻辑?
按钮组件的完整代码如下
import { useEffect, useState } from "react";
import { logosHooks } from "@/hooks/logos-hooks";
import { cn } from "@/lib/utils";
const SidePanelTrigger = () => {
const logo = logosHooks.useLogoIcon();
const [show, setShow] = useState(false);
useEffect(() => {
const checkPanelState = async() => {
const contexts: chrome.runtime.ExtensionContext[] = await chrome.runtime.getContexts({ contextTypes: ["SIDE_PANEL"] });
setShow(contexts.length !== 0);
}
checkPanelState();
}, []);
const handleOpenSidepanel = () => {
chrome.runtime.sendMessage({ action: "openSidePanel" });
}
return (
<button
className={cn(
"flex fixed top-[200px] z-10 -right-[10px] bg-primary rounded-l-sm justify-center items-center transition-all duration-300 hover:right-0 p-3 shadow-lg cursor-pointer",
show && "hidden"
)}
onClick={handleOpenSidepanel}
>
Button
</button>
);
};
export default SidePanelTrigger;
我稍微改变了代码并设法解决了这个问题。
对我有用的解决方案是使用
ResizeObserver
。每次侧面板打开或关闭时,它都会更改活动选项卡的宽度。我附加了 checkPanelState
函数,该函数使用 ResizeObserver
检查侧面板是否关闭或打开以调整大小事件。我还添加了去抖动来优化代码。
该组件的完整代码如下
import { useEffect, useState } from "react";
import { logosHooks } from "@/hooks/logos-hooks";
import { cn, debounce } from "@/lib/utils";
const SidePanelTrigger = () => {
const logo = logosHooks.useLogoIcon();
const [show, setShow] = useState(false);
useEffect(() => {
const checkPanelState = async() => {
// @ts-ignore
const contexts: chrome.runtime.ExtensionContext[] = await chrome.runtime.getContexts({ contextTypes: ["SIDE_PANEL"] });
setShow(contexts.length === 0);
}
const debouncedCheck = debounce(checkPanelState, 50);
const resizeObserver = new ResizeObserver(debouncedCheck);
resizeObserver.observe(document.body);
return () => resizeObserver.disconnect();
}, []);
const handleOpenSidepanel = () => {
setShow(false)
chrome.runtime.sendMessage({ action: "openSidePanel" });
}
return (
<button
className={cn(
"hidden fixed top-[200px] z-10 -right-[10px] bg-primary rounded-l-sm justify-center items-center transition-all duration-300 hover:right-0 p-3 shadow-lg cursor-pointer",
show && "flex"
)}
onClick={handleOpenSidepanel}
>
Button
</button>
);
};
export default SidePanelTrigger;