You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Chrome扩展开发:如何在侧边栏关闭时触发状态检查以控制按钮显示/隐藏

Chrome扩展开发:如何在侧边栏关闭时触发状态检查以控制按钮显示/隐藏

我之前也碰到过类似的Chrome扩展开发问题,focus/blur事件在Chrome里确实不太靠谱,不过有几个更稳定的方案能解决你的需求,咱们一步步来梳理:

方案一:利用Chrome官方的SidePanel事件(推荐)

Chrome 114及以上版本提供了chrome.sidePanel.onShownchrome.sidePanel.onHidden原生事件,专门用来监听侧边栏的显示/隐藏状态,这是最可靠的实现方式。

步骤1:在Background脚本中监听侧边栏状态

首先在你的background.ts(或service-worker.ts)里添加事件监听,当侧边栏状态变化时,向对应标签页发送消息:

// background.ts
chrome.sidePanel.onShown.addListener(({ tabId }) => {
  // 侧边栏打开时,通知对应标签页
  chrome.tabs.sendMessage(tabId, { action: "sidePanelOpened" });
});

chrome.sidePanel.onHidden.addListener(({ tabId }) => {
  // 侧边栏关闭时,通知对应标签页
  chrome.tabs.sendMessage(tabId, { action: "sidePanelClosed" });
});

步骤2:在按钮组件中接收消息并更新状态

修改你的SidePanelTrigger组件,添加消息监听,同时保留初始化时的状态检查逻辑:

import { useEffect, useState } from "react";
import { logosHooks } from "@/hooks/logos-hooks";
import { cn } from "@/lib/utils";

const SidePanelTrigger = () => {
  const logo = logosHooks.useLogoIcon();
  const [showButton, setShowButton] = useState(false);

  useEffect(() => {
    // 初始化时检查侧边栏状态
    const checkPanelState = async () => {
      const contexts: chrome.runtime.ExtensionContext[] = await chrome.runtime.getContexts({ 
        contextTypes: ["SIDE_PANEL"] 
      });
      // 逻辑:侧边栏打开则隐藏按钮,关闭则显示按钮
      setShowButton(contexts.length === 0);
    };

    // 监听来自Background的状态消息
    const handleSidePanelMessage = (message: { action: string }) => {
      switch(message.action) {
        case "sidePanelOpened":
          setShowButton(false); // 侧边栏打开,隐藏按钮
          break;
        case "sidePanelClosed":
          setShowButton(true); // 侧边栏关闭,显示按钮
          break;
      }
    };

    // 执行初始化检查并注册消息监听
    checkPanelState();
    chrome.runtime.onMessage.addListener(handleSidePanelMessage);

    // 组件卸载时移除监听,避免内存泄漏
    return () => {
      chrome.runtime.onMessage.removeListener(handleSidePanelMessage);
    };
  }, []);

  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",
        !showButton && "hidden" // 逻辑直观化:不需要显示时隐藏按钮
      )}
      onClick={handleOpenSidepanel}
    >
      Button
    </button>
  );
};

export default SidePanelTrigger;

方案二:在侧边栏组件中主动发送状态消息

如果你的Chrome版本较低,不支持sidePanel原生事件,可以在侧边栏组件里,利用组件的挂载/卸载生命周期来发送状态消息:

步骤1:在侧边栏组件中发送消息

假设你的侧边栏组件是SidePanel.tsx,添加以下代码:

import { useEffect } from "react";

const SidePanel = () => {
  useEffect(() => {
    // 侧边栏挂载(打开)时,通知当前活跃标签页
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      if (tabs[0]?.id) {
        chrome.tabs.sendMessage(tabs[0].id, { action: "sidePanelOpened" });
      }
    });

    // 侧边栏卸载(关闭)时,通知当前活跃标签页
    return () => {
      chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
        if (tabs[0]?.id) {
          chrome.tabs.sendMessage(tabs[0].id, { action: "sidePanelClosed" });
        }
      });
    };
  }, []);

  // 侧边栏内容
  return <div>Side Panel Content</div>;
};

export default SidePanel;

步骤2:按钮组件的处理和方案一相同

同样在SidePanelTrigger组件中添加消息监听逻辑即可。

注意事项

  • 确保你的manifest.json中声明了必要的权限:
    {
      "permissions": ["sidePanel", "tabs"],
      "side_panel": {
        "default_path": "sidepanel.html"
      }
    }
    
  • 你之前尝试在主组件的useEffect返回函数中发送消息没用,是因为这个返回函数只有主组件卸载时才会触发,和侧边栏的关闭没有关联,所以无法捕获侧边栏的关闭事件。

备注:内容来源于stack exchange,提问作者asus18019

火山引擎 最新活动