Bilibili-Evolved 组件源码解析禁用评论区搜索词链接disable-search-link【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved导读本文以 Bilibili-Evolved 仓库中的「禁用评论区搜索词」组件disable-search-link为切入点完整解析该功能从需求到实现的技术细节它如何兼容新版V3与旧版两种评论区结构、如何借助 Shadow DOM 事件与事件拦截双通道分别处理搜索词链接、如何用!important样式兜底以及组件的加载/卸载生命周期设计。读完本文你既能直接上手启用该功能也能理解 Bilibili-Evolved 评论区组件与 Shadow DOM 观察体系的核心工作原理为编写同类评论区增强组件提供可复用的实现范式。一、功能是什么在哔哩哔哩的评论区中部分评论内容里包含的搜索词会被渲染为可点击的跳转链接旧版评论区表现为.jump-link.search-word与.icon.search-word元素新版评论区表现为a>const name disableCommentsSearchLink let prevent false export const component defineComponentMetadata({ name, displayName: 禁用评论区搜索词, instantStyles: [ { name, style: () import(./disable-search-link.scss), important: true, }, { name, style: () import(./disable-search-link-shadow.scss), shadowDom: true, }, ], tags: [componentsTags.utils, componentsTags.style], entry: async () { /* ... */ }, reload: () { prevent true }, unload: () { prevent false }, })几个值得注意的元数据细节instantStyles与两套样式组件声明了两份即时加载的样式。第一份 disable-search-link.scss 作用于普通 DOM并标记important: true生成规则时自动追加!important第二份 disable-search-link-shadow.scss 设置了shadowDom: true用于注入到 Shadow DOM 内部——这是新版评论区Web Component Lit 渲染所必需的。tags归属组件被归类为utils工具与style样式两类标签说明它本质上是以样式为主、辅以事件拦截的增强组件在设置面板中按这两个标签均可检索到。模块级状态prevent组件使用模块级布尔变量prevent作为是否启用拦截的开关由entry置为true、reload重新置为true、unload置为false三者协同维护避免重复监听。三、前置基础Bilibili-Evolved 的评论区抽象要理解该组件的实现需要先了解仓库中评论区的抽象体系。src/components/utils/comment-apis.ts对外暴露了统一的遍历 APIcomment-apis.ts/** 为每一个评论区执行操作 */ export const forEachCommentArea (callback: CommentAreaCallback) { commentAreaManager.forEachCommentArea(callback) }其底层CommentAreaManager通过allMutations全局 MutationObserver监听整个文档识别选择器.bili-comment, .bb-comment, bili-comments匹配的节点作为评论区comment-area-manager.ts并交由工厂函数getCommentArea分派到具体实现comment-area.tsexport const getCommentArea (element: HTMLElement): CommentArea { if (CommentAreaV3.isV3Area(element)) { return new CommentAreaV3(element) } if (CommentAreaV2.isV2Area(element)) { return new CommentAreaV2(element) } return new CommentAreaV1(element) }由此可知仓库将评论区划分为三代版本判定方式结构特点V3element.tagName.toLowerCase() bili-comments新版 Web Component内容渲染在 Shadow DOM 内使用 Lit 框架见 areas/v3.tsV2isV2Area(element)旧版结构.bili-comment等DOM 直接可见V1兜底更早期的评论区结构「禁用评论区搜索词」组件的entry正是基于area instanceof CommentAreaV3的判断将新版与旧版评论区拆成两条完全不同的处理路径。四、核心实现两条处理路径4.1 新版评论区V3Shadow DOM 内的属性剥离新版评论区使用 Web Component其内部 DOM 位于 Shadow Root 中普通 MutationObserver 与事件委托无法直接触达。组件针对 V3 的路径index.tsconst isV3Area area instanceof CommentAreaV3 if (isV3Area) { area.commentAreaEntry.addEventListener( ShadowRootEvents.Updated, (e: CustomEventMutationRecord[]) { const records e.detail records.forEach(record { record.addedNodes.forEach(node { const isCommentLink node instanceof HTMLAnchorElement node.getAttribute(data-type) search if (!isCommentLink) { return } node.removeAttribute(href) node.removeAttribute(target) }) }) }, ) }这里依赖两个关键设施ShadowRootEvents.Updated这是仓库 shadow-root 模块自定义的 DOM 事件见 v3.ts 中同类事件的使用方式其detail携带MutationRecord[]由ShadowDomObserver在监听 Shadow DOM 变更时派发。组件监听该事件即可感知 V3 评论区内部的节点增删无需自行观察 Shadow Root。data-typesearch特征新版评论区渲染搜索词链接时会在a元素上标记data-typesearch。组件以此作为唯一判定条件命中后直接执行removeAttribute(href)与removeAttribute(target)——href被移除后链接不再可跳转target被移除后即使残留样式也不会新开标签页。这种观察新增节点 特征属性判定 属性剥离的方式是典型的新版评论区处理范式同类组件如 copy-link也遵循forEachCommentArea Shadow DOM 事件的架构。4.2 旧版评论区V1/V2事件拦截旧版评论区没有 Shadow DOM 隔离搜索词链接是普通可点击元素。组件使用preventEvent在捕获阶段拦截点击index.tspreventEvent(area.element, click, e { if (!(e.target instanceof HTMLElement) || !prevent) { return false } const element e.target as HTMLElement if ( [.jump-link.search-word, .icon.search-word].some(selector element.matches(selector), ) ) { return true } return false })选择器集合.jump-link.search-word是旧版评论区搜索词跳转链接的 class 组合.icon.search-word则对应其附带的小图标放大镜图标两者都会被拦截。回调语义preventEvent的回调返回true表示阻止该事件阻止默认行为与冒泡返回false表示放行。这里通过prevent开关兜底——组件卸载后即便回调残留也会因prevent false而放行事件保证卸载干净。4.3 两条路径的对比维度V3新版V1/V2旧版技术手段监听ShadowRootEvents.Updated操作MutationRecordpreventEvent捕获阶段拦截click判定依据node instanceof HTMLAnchorElement >.search-word { .icon { display: none !important; } // 需要比夜间模式的优先级高 .reply-warp .reply-item .jump-link { color: inherit !important; cursor: text !important; } }隐藏放大镜图标.search-word.icon将.jump-link的颜色改为inherit跟随正文、鼠标指针改为cursor: text并注明需要比夜间模式的优先级高——即必须用!important压过夜间模式等主题样式的干扰。Shadow DOM 样式disable-search-link-shadow.scss:host(bili-rich-text) { #contents a[data-typesearch] { color: inherit !important; cursor: inherit !important; display: contents !important; img { display: none; } } }通过:host(bili-rich-text)限定作用于新版评论区富文本宿主对a[data-typesearch]统一继承颜色与光标、以display: contents消除其作为链接盒子的干扰并隐藏内部的img图标。可见该组件在功能上剥离跳转与视觉上还原纯文本两个层面做了双保险即使某条路径如新版评论区的事件未及时触发暂时失效样式兜底也能保证视觉上不再呈现为可点击链接。六、生命周期与卸载安全性组件通过三个钩子维护状态entry: async () { prevent true /* 注册监听 */ }, reload: () { prevent true }, unload: () { prevent false },entry首次启用时置prevent true并注册各评论区的监听器reload设置面板中调整相关配置后组件重载重新置prevent trueunload禁用组件时置prevent false使旧版评论区的preventEvent回调形同虚设事件不再被阻止配合CommentAreaManager对移除评论区的清理逻辑见 comment-area-manager.ts实现无残留卸载。七、如何启用与验证该组件随 Bilibili-Evolved 主脚本打包发布用户无需单独安装在哔哩哔哩页面打开 Bilibili-Evolved 的设置面板在「评论区」相关分类下或在搜索框输入禁用评论区搜索词英文标识disableCommentsSearchLink找到该组件开启开关后刷新评论或滚动加载更多评论即可看到效果原搜索词不再可点击跳转颜色与光标与正文一致。验证要点供开发与回归测试参考旧版评论区检查.jump-link.search-word元素点击后是否仍触发跳转应不跳转图标是否隐藏新版评论区检查 Shadow DOM 内a[data-typesearch]的href、target属性是否被移除启用夜间模式等主题后确认搜索词颜色仍与正文一致依赖!important兜底规则切换组件开关reload/unload确认卸载后点击行为恢复、无重复监听报错。八、总结与可复用经验「禁用评论区搜索词」是一个小而完整的评论区增强组件范本其可复用的工程经验包括双通道兼容通过area instanceof CommentAreaV3分流Shadow DOM 场景用ShadowRootEvents.Updated 属性剥离传统 DOM 场景用preventEvent事件拦截一套组件同时覆盖两代评论区特征属性判定以data-typesearch、.search-word等稳定的标记作为识别依据而非脆弱的文本内容匹配功能与样式分离兜底事件/属性层负责不可跳转SCSS 层含 Shadow DOM 注入负责不像链接并以!important对抗主题优先级状态开关式卸载用模块级prevent布尔值让卸载后的回调自动失效规避重复监听与泄漏。参考实现文件组件入口 index.ts、普通样式 disable-search-link.scss、Shadow 样式 disable-search-link-shadow.scss、评论区抽象 comment-apis.ts 与 comment-area-manager.ts。【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
