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

背景

开发谷歌插件的过程中,监听用户浏览器操作行为,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的事件。
相关推荐
恋猫de小郭35 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端