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

Chrome扩展报错:Uncaught TypeError: 无法读取undefined的onActivated属性

问题根源分析

  1. Background.js语法错误:代码末尾多余的});导致脚本解析失败,进而chrome.tabs无法正常初始化,出现undefined的情况。
  2. 消息发送方式错误:使用chrome.runtime.sendMessage会广播给所有监听者,无法精准定位到当前激活的标签页,导致目标内容脚本收不到消息。
  3. 内容脚本逻辑错位:按钮属于popup页面的元素,内容脚本(注入到网页中)无法获取popup里的#stop元素,点击事件绑定完全无效。

修复方案

1. 修复Background.js的语法错误并调整消息发送逻辑

删掉末尾多余的});,改用chrome.tabs.sendMessage向当前激活的标签精准发送消息:

console.log(typeof chrome.tabs);
if (chrome.tabs?.onActivated) {
  chrome.tabs.onActivated.addListener(function(activeInfo) {
    // 向当前激活的标签发送start消息,并处理可能的错误
    chrome.tabs.sendMessage(activeInfo.tabId, {data: "start"}, (response) => {
      if (chrome.runtime.lastError) {
        console.log("标签页未加载内容脚本:", chrome.runtime.lastError.message);
      } else {
        console.log("消息已发送给标签:", activeInfo.tabId);
      }
    });
  });
} else {
  console.log("无法访问chrome.tabs.onActivated");
}

2. 调整内容脚本逻辑(index.js)

移除popup按钮的绑定逻辑,专注于接收background的消息并记录开始时间,同时暴露时长计算方法:

let start;

console.log("内容脚本已加载");

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.data === "start") {
    console.log("收到start消息");
    start = new Date();
    sendResponse({status: "success"}); // 回复background确认收到
  } else if (request.data === "getDuration") {
    if (!start) {
      sendResponse({duration: null});
      return;
    }
    const stop = new Date();
    const mili = stop.getTime() - start.getTime();
    const all_sec = mili * 0.001;
    const sec = Math.round(all_sec) % 60;
    const min = Math.floor(all_sec / 60);
    sendResponse({duration: {min, sec}});
  }
  return true; // 保持消息通道开放,支持异步回复
});

3. 新增Popup.js处理按钮点击事件

创建popup.js,绑定popup中按钮的点击事件,主动向当前标签的内容脚本请求时长:

document.addEventListener('DOMContentLoaded', function () {
  const stopBtn = document.getElementById("stop");
  stopBtn.addEventListener("click", function() {
    // 获取当前激活的标签
    chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
      const activeTab = tabs[0];
      // 向当前标签的内容脚本请求时长
      chrome.tabs.sendMessage(activeTab.id, {data: "getDuration"}, (response) => {
        if (chrome.runtime.lastError) {
          alert("无法获取时长:标签未加载计时器");
          return;
        }
        const duration = response.duration;
        if (!duration) {
          alert("Timer is not started yet.");
        } else {
          const time = `min : ${duration.min}      sec : ${duration.sec}`;
          alert(time);
        }
      });
    });
  });
});

同时在popup.html中引入该脚本:

<!-- popup.html示例 -->
<!DOCTYPE html>
<html>
<head>
  <style>button { padding: 8px 16px; }</style>
</head>
<body>
  <button id="stop">查看停留时长</button>
  <script src="popup.js"></script>
</body>
</html>

4. 确认Manifest.json配置正确

确保content_scripts和资源引用无误:

{
  "manifest_version": 2,
  "name": "Time tracker",
  "version": "1.0.1",
  "description": "Keep track of your time on every tab ",
  "permissions": ["tabs", "runtime"],
  "content_scripts": [{
    "matches": ["*://*/*"],
    "js": ["index.js"],
    "run_at": "document_end"
  }],
  "browser_action": {
    "default_title": "Time tracker", 
    "default_popup": "popup.html"  
  },
  "background": {
    "scripts": ["background.js"],
    "persistent": true
  }
}

关键说明

  • 语法错误是chrome.tabs为undefined的直接原因,必须优先修复。
  • 使用chrome.tabs.sendMessage指定tabId,避免广播消息导致的逻辑混乱,确保只有目标标签收到计时启动指令。
  • 严格分离职责:background负责监听标签切换,内容脚本负责记录时间,popup负责UI交互,避免跨上下文的逻辑错位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 22:07:28