You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Popup与Content脚本双向通信及动态数据获取问题咨询

问题根因

  • Content脚本中chrome.runtime.onMessage.addListener被放在MutationObserver回调内,每次DOM变更都会重复注册监听器,旧监听器会一直持有历史listData的引用,导致响应Popup请求时返回过期数据
  • Content脚本没有将最新的listData存储在全局作用域,监听器无法获取每次DOM更新后的最新数据
  • Popup关闭后上下文会被销毁,Content主动发送的消息无接收方,这种推送逻辑不适用Popup的临时运行场景
  • Popup中getLeadList注册的chrome.runtime.onMessage没有销毁逻辑,多次调用会导致内存泄漏,且Promise仅能resolve一次,无法响应后续更新

修复代码

1. Content.tsx 修复

// 全局存储最新的listData
let latestListData: Array<any> = [];

// 消息监听仅注册一次,永远返回最新的listData
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.greeting === 'hello') {
    sendResponse(latestListData);
  }
  // 处理Popup触发的页面刷新请求
  if (request.action === 'reloadPage') {
    window.location.reload();
  }
  return true; // 避免响应通道提前关闭,异步响应必须加该参数
});

// MutationObserver仅负责更新全局listData
new MutationObserver(() => {
  const dataImage = document.getElementsByClassName('image');
  const dataName = document.getElementsByClassName('name');
  const dataTitle = document.getElementsByClassName('title');

  const newListData: Array<any> = [];
  for (let x = 0; x < dataImage.length; x++) {
    const image = dataImage[x]?.firstElementChild?.src;
    const name = dataName[x]?.innerText;
    const title = dataTitle[x]?.firstElementChild?.innerText;
    const web = dataName[x]?.firstElementChild?.href;

    newListData.push({ image, name, title, web });
  }
  // 覆盖更新全局数据
  latestListData = newListData;
}).observe(document, { subtree: true, childList: true });

2. Popup.tsx 修复

// 每次调用主动从Content拉取最新数据
getLeadList(query: Object): Promise<LeadResult[]> {
  return new Promise<LeadResult[]>((resolve) => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      chrome.tabs.sendMessage(
        tabs[0].id,
        { greeting: 'hello' },
        (response) => {
          resolve(response || []);
        }
      );
    });
  });
}

// 新增:主动刷新Content所在页面的方法
reloadContentPage(): Promise<void> {
  return new Promise((resolve) => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      chrome.tabs.sendMessage(
        tabs[0].id,
        { action: 'reloadPage' },
        () => resolve()
      );
    });
  });
}

功能验证

  • Popup每次打开调用getLeadList都能拿到MutationObserver更新后的最新数据
  • 页面滚动DOM更新后,重新打开Popup即可自动获取最新列表
  • 调用reloadContentPage即可触发Content页面刷新,效果和window.reload完全一致

内容的提问来源于stack exchange,提问作者user16691768

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:06:04