0%

客户端删除DOM节点的几种方式

B站首页有一些板块实在是辣眼睛,所以得想办法处理一下。

needremovebilibili.jpg

准备工作

我常用的浏览器是Chrome,所以就用Tampermonkey来加载脚本。

原理也很简单,等页面加载完成后,我们可以用Tampermonkey再跑一段自定义的JavaScript,用来操作DOM树。

然后通过Chrome的审查元素,得知,需要去除的元素id分别为bili_report_livereportFirst2

Version 1

根据我十分浅薄的前端知识,写下了非常naïve的两行:

1
2
document.getElementById("bili_report_live").remove();
document.getElementById("reportFirst2").remove();

实验发现,在REPL(Console tab in dev tools)里输入这两行是可行的,但是放在Tampermonkey中,就不行了。

没关系,我们依然可以在REPL中看见报错信息:

1
2
Uncaught TypeError: Cannot read property 'remove' of null
...

NPE了,推测是脚本执行时机的问题,Tampermonkey执行脚本的时候,我们需要的节点还没有生成。

Version 2

既然如此,我们尝试等待一会儿再执行。

1
2
setTimeout(() => document.getElementById("bili_report_live").remove(), 500)
setTimeout(() => document.getElementById("reportFirst2").remove(), 500)

尝试了下500ms的超时,在大多数情况下可以正确处理,但是如果网络波动了,就会失败。

除此之外,还有点令人不爽,你会看着这两块内容先出现,再消失

看看还有没有别的办法。

Version 3

CSS的id selector是个好选择,DOM树中有了就自动应用样式,没有的话也不影响。

1
2
3
4
5
6
(document.head || document.documentElement)
.insertAdjacentHTML('beforeend',
'<style>#bili_report_live { display: none!important; }</style>');
(document.head || document.documentElement)
.insertAdjacentHTML('beforeend',
'<style>#reportFirst2 { display: none!important; }</style>');

Version 4

这个需求其实有个简单的思路:我希望能在DOM树变更的时候被通知到。

在MDN搜索了一下,果然有这个API:MutationObserver

这样写也就OK了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new MutationObserver(function(mutations) {
const e = document.getElementById("bili_report_live")
if (e) {
e.remove();
this.disconnect();
}
}).observe(document, {childList: true, subtree: true});

new MutationObserver(function(mutations) {
const e = document.getElementById("reportFirst2")
if (e) {
e.remove();
this.disconnect();
}
}).observe(document, {childList: true, subtree: true});

小结

v3和v4都是不错的方法,能够完美解决这个问题,我的前端知识又前进了一小步。

现在b站首页看起来就是这个样子了,很清爽,哈哈哈哈哈哈。

IMG_5192.PNG

完整脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// ==UserScript==
// @name 去除bilibili推广栏和直播栏
// @namespace http://tampermonkey.net/
// @version 0.2
// @description try to take over the world!
// @author You
// @match https://www.bilibili.com/
// @grant none
// ==/UserScript==

(function() {
'use strict';

// Your code here...=
// v3
// (document.head || document.documentElement)
// .insertAdjacentHTML('beforeend',
// '<style>#bili_report_live { display: none!important; }</style>');
// (document.head || document.documentElement)
// .insertAdjacentHTML('beforeend',
// '<style>#reportFirst2 { display: none!important; }</style>');
// v4
new MutationObserver(function(mutations) {
const e = document.getElementById("bili_report_live")
if (e) {
e.remove();
this.disconnect(); // disconnect the observer
}
}).observe(document, {childList: true, subtree: true});
new MutationObserver(function(mutations) {
const e = document.getElementById("reportFirst2")
if (e) {
e.remove();
this.disconnect(); // disconnect the observer
}
}).observe(document, {childList: true, subtree: true});
})();