谷歌浏览器插件 录制菜单路由跳转行为 事件重复解决方案

背景

开发谷歌插件的过程中,监听用户浏览器操作行为,vue3 项目使用hash路由,发现在 background 脚本中通过chrome.tabs.onUpdated和chrome.webNavigation.onHistoryStateUpdated事件监听时,点击切换菜单路由时都会触发一个链接跳转事件,导致监听事件重复。

这里说明一下为什么在chrome.tabs.onUpdated和chrome.webNavigation.onHistoryStateUpdated事件都写了那个链接跳转事件,是因为发现在某些网站上有时候chrome.tabs.onUpdated会触发,有时候chrome.webNavigation.onHistoryStateUpdated会单独触发,为了兼容处理各种情况,所以就在这两个事件里都处理了链接跳转事件,结果引发了文章开头描述的问题

思考过程

引发上述问题可能的原因包括:

  1. 事件触发条件重叠:当Hash变化时,chrome.tabs.onUpdated可能因为URL变化而触发,而chrome.webNavigation.onHistoryStateUpdated则因为历史状态改变而触发,两者同时发生。
  2. 事件监听器的重复注册:可能在插件的不同地方多次注册了相同的监听器,导致重复触发。
  3. 事件传播或页面加载阶段的问题:比如在页面加载的不同阶段,两个事件可能被多次触发。

接下来,我需要考虑如何解决这个问题。可能的解决方案包括:

  • 合并事件监听:将两个事件的监听逻辑合并,避免重复处理。例如,将两个事件的回调函数统一到一个处理函数中,并添加防重机制。
  • 条件判断过滤:在事件回调中添加条件判断,比如检查URL变化是否是Hash变化,或者是否是用户主动触发的路由跳转,从而决定是否执行逻辑。
  • 使用防重或节流:在回调函数中使用防重(如setTimeout和clearTimeout)或节流来避免短时间内多次触发。
  • 选择更精确的事件监听:如果Hash路由主要通过hashchange事件触发,可能只需要监听chrome.webNavigation.onHistoryStateUpdated,而chrome.tabs.onUpdated可能包含更多的触发场景,可以考虑移除其中一个监听。(PASS,原因看开头背景说明)

解决方案

1. 合并事件监听逻辑,避免重复处理

js 复制代码
// 合并后的处理函数
function handleUrlChange(details) {
  if (isHandling) return; // 防止重复触发
  isHandling = true;

  // 具体处理逻辑(如获取当前URL的Hash值,上报动作)
  
  // 具体处理逻辑

  // 延迟重置标志位,避免短时间内重复触发
  setTimeout(() => {
    isHandling = false;
  }, 200); // 根据需求调整延迟时间
}

// 监听 chrome.tabs.onUpdated
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.url && changeInfo.url.includes('#')) {
    handleUrlChange({ url: changeInfo.url });
  }
});

// 监听 chrome.webNavigation.onHistoryStateUpdated
chrome.webNavigation.onHistoryStateUpdated.addListener((details) => {
  handleUrlChange(details);
});

2. 过滤非必要的触发条件

在回调函数中添加条件判断,比如 仅在Hash值变化时执行逻辑,根据自己项目实际情况进行判断。

js 复制代码
function handleUrlChange(details) {
  const currentUrl = details.url || chrome.tabs.getSelected().url;
  const newHash = new URL(currentUrl).hash;

  // 获取上一次记录的Hash值(需维护一个变量)
  if (lastHash === newHash) return; // 如果Hash未变化,直接返回
  lastHash = newHash;

  // 执行实际逻辑
  console.log('Hash changed:', newHash);
}

关键注意事项

  1. 防重机制

    • 使用标志位(如isHandling)或节流函数(如setTimeout)防止短时间内重复触发。
  2. 状态维护

    • 通过lastHash记录上一次的Hash值,避免重复处理相同Hash的事件。
相关推荐
XPoet42 分钟前
AI 编程工程化:实战——从 0 到 1 搭建 AI 编程工作流
前端·后端·ai编程
-今昭-1 小时前
Logstash 管理
java·服务器·前端
名字还没想好☜1 小时前
React 用自定义 useDebounce Hook 治好搜索框频繁请求:防抖、竞态取消与卸载清理
前端·javascript·react.js·react·hooks
杉氧1 小时前
Flutter 跨平台多端适配与 Android/iOS 一键自动化打包发布
android·前端·flutter
障碍的枫子1 小时前
xss和CSRF的攻击和防御
前端·xss·csrf
用户921080262862 小时前
3. 给 Bubble 新增一个 Agent Variant
前端
抓不住时间的沙2 小时前
butterfly主题美化,打造属于自己的个性博客
java·开发语言·前端·javascript·node.js·github
kyriewen2 小时前
前端切图仔被 AI 新闻淹死的第 N 天,我用 TRAE Work 定时任务救了自己
前端·人工智能·trae
京东云开发者2 小时前
【全栈实践】第一个 AI Agent 项目:从零搭建 AI 音频创作助手(高级篇)
前端·agent·音视频开发
AbrahamCS2 小时前
从角色协同到可运行图:Graph Engineer 与多智能体编排
前端·人工智能·智能体