本帖最后由 三滑稽甲苯 于 2023-6-2 14:35 编辑
前言
在浏览网页的时候,总会有那么几个网站,在你选择了文本后给你弹出一个悬浮框,让你可以 方便 地在它的搜索引擎上搜索。实际上,我们往往只是想要复制,或者只是下意识地双击选择(不知道有没有人和我一样有这样的习惯),而跳出来的搜索框很容易误触。终于,某一天我忍无可忍,决定下手解决这种情况。
思路
经过 F12 分析后,发现绝大多数网站都是通过监听 selectionchange 和 mouseup 这两种事件来控制悬浮框的展现。于是,一个通杀方案浮现在脑海之中,那就是移除所有监听这两个事件的监听器。但是移除监听器需要知道它的回调函数,而我们很难做到通用地获取回调函数 (通过覆写 addEventListener 方法可以做到劫持,但是这么做可能导致意料之外的错误)。
在翻看了十段甚至九段文档后,我发现了一个参数:
options (可选)
一个指定有关 listener 属性的可选参数对象。可用的选项如下:
capture (可选)
一个布尔值,表示 listener 会在该类型的 事件捕获阶段 传播到该 EventTarget 时触发。
要弄明白上述参数的含义,得首先弄清楚 js 的事件顺序。当某个元素发起事件时,首先从最顶层传播至发起的元素,然后再次折返传播到最顶层。第一趟称为事件捕获阶段 (Event capturing),第二趟称为事件冒泡阶段 (Event bubbling)。用人话来说就是 capture 为真时,最顶层的事件监听器会首先获得事件通知。
同时我们知道,在事件监听器的回调函数中,我们可以 调用 stopImmediatePropagation 来立刻阻止事件传播。那么,一个优雅而又通用的解决方案就呼之欲出了。
最终方案
- 我们直接在整个
document 上设立关于 selectionchange 和 mouseup 的监听器,capture 设为 true ,从而保证我们的侦听器是最早获得事件通知的
- 当我们的侦听器得到通知后,调用
stopImmediatePropagation 来立刻阻止事件传播
- 目标网站设立的侦听器无法捕获事件 (因为已经被我们的侦听器截获了)
用人话来讲,就是我们设立了一个侦听器,截获了所有相关事件,导致网站设立的侦听器 不知道 这些事件,于是悬浮框也就不会出现了。需要注意的是,有些网站是通过这两类事件来提供其它有用的服务,在这种情况下只能使用其它方法了(这类网站大概率也不会搞个悬浮框来恶心用户吧)。
代码
Talk is cheap, show me the code.
// 核心代码
["selectionchange", "mouseup"].forEach((type) => {
document.addEventListener(type, (e) => {
e.stopImmediatePropagation();
}, {capture: true});
});
油猴:https://greasyfork.org/zh-CN/scripts/466779-%E7%A6%81%E7%94%A8%E6%90%9C%E7%B4%A2%E6%A1%86
注意:对于不在脚本内置列表内的网站,你可以手动将其 添加至用户匹配列表 来使脚本生效,详见链接内的截图。
|