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

背景

开发谷歌插件的过程中,监听用户浏览器操作行为,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的事件。
相关推荐
JustHappy3 小时前
古法编程秘籍(七):互联网到底是什么?把两台电脑怎么说话搞懂就够了
前端·后端·网络协议
老毛肚3 小时前
jeecg-boot-base-core 02 day
javascript·python
snow@li3 小时前
SEO-文章标题:写文章时候,分类+主标题+大纲+解释 作为标题 / 不点进去也知道全文覆盖什么 / 标题即架构
前端
kyriewen4 小时前
Git Commit 前自动修复代码风格?配置 Husky + lint-staged,从此 CR 只聊逻辑
前端·git·面试
小和尚同志4 小时前
AI 自动化测试探索(一):Playwright MCP
前端·人工智能·aigc
老马识途2.04 小时前
在AI的帮助下理解spring的启动过程
java·前端·spring
徐小夕5 小时前
Loop Engineering 深度解析与实战指南(全网最全)
前端·算法·github
运筹vivo@5 小时前
Python ContextVar 底层机制与内存模型拆解
前端·数据库·python
#麻辣小龙虾#6 小时前
基于vue3.0开发一款【固废与废气运维管理系统】(支持源码)
前端·vue.js·vue3
Cosolar6 小时前
Docsify零构建文档站完全指南:从快速搭建到企业级部署
前端·开源·github