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

背景

开发谷歌插件的过程中,监听用户浏览器操作行为,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的事件。
相关推荐
To_OC4 小时前
写了三遍 Todo List,我终于搞懂了 React 父子组件到底怎么通信
前端·javascript·react.js
勇往直前plus5 小时前
Vue3(篇一) 核心概念——响应式模板语法与组件基础
前端·javascript·vue.js
咩咩啃树皮5 小时前
第43篇:Vue3计算属性(computed)完全精讲——缓存机制、依赖计算、业务最优解
前端·vue.js·缓存
用户938515635076 小时前
从零搭建 AI 日记助手:用 Milvus 向量数据库 + RAG 让机器读懂你的每一天
javascript·人工智能·全栈
徐小夕7 小时前
花了一周,3亿tokens,我开源了一款 Word 文档智能审查平台,文稿自动质检+可视化分析,告别低效人工审核
前端·算法·github
a1117767 小时前
坦克大战3D Three.js 3D (开源项目)
开发语言·javascript·3d
kyriewen8 小时前
别再乱用useEffect了——你写的10个里有8个不该存在
前端·javascript·react.js
Ivanqhz8 小时前
Rust &‘static str浅析
java·前端·javascript·rust
IT_陈寒9 小时前
SpringBoot这个分页坑,我踩了三天才爬出来
前端·人工智能·后端
颜酱9 小时前
05 | 召回前置准备:根据业务数据库生成各数据库(读取配置阶段)
前端·人工智能·后端