背景
相信大家都会有类似的经历,当我们在浏览微博查看他人的照片墙时,在我们不断向下滑动查看照片的过程中,照片墙上方的图片不会被清除,当查看的照片过多时,页面会明显变卡,在这种情况下,笔者常常通过Chrome控制台进行DOM操作清理顶部的图片后继续浏览。
插件安装(请使用Chrome浏览器打开)
View in Chrome App Store
插件源码
github.com/Soulghost/W…。
原理
微博照片墙的每张照片的DOM结点都属于photo_module
类,为了清除顶部照片,只需要通过DOM树找到所有的photo_module
结点,然后清理结点数组中前半部分的元素,仅留下当前屏幕范围内的结点,从而达到减轻渲染压力,又不会影响到正常浏览。
通过控制台调试
首先我们任意打开一个人的微博照片墙,这里以绿帽社为例,首先打开用户的照片墙,然后开启控制台,在控制台键入如下代码来引入jQuery方便DOM操作。
var f=document.createElement('script')
f.setAttribute("type","text/javascript")
f.setAttribute("src", 'https://static.zqgame.com/js/jquery-1.7.2.min.js')
document.getElementsByTagName("head")[0].appendChild(f);
复制代码
随后,我们尝试选取所有的照片结点。
>> $('.photo_module')
>> init(96) [li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, li.photo_module, prevObject: init(1), context: document, selector: ".photo_module"]
复制代码
如果选择器正确返回结点数组,说明jQuery已经成功引入,接下来就可以循环移除顶部照片了。
let $photos = $('.photo_module');
let len = $photos.length;
// 保留最后20张照片
for (let i = 0; i < len - 20; i++) {
$photos[i].remove();
}
复制代码
以上我们只是通过控制台移除了照片,十分不便,下面进入正题,通过开发插件将逻辑包含在内。
开发Chrome插件
Chrome插件拥有独立的DOM空间,因此直接通过插件的逻辑代码是无法操作到页面DOM的,我们需要通过插件将js、css等注入到页面中进行操作。
Chrome插件由描述文件、资源和代码三部分构成,描述文件类似于Android的Manifest以及iOS的Info.plist,用于描述应用的版本、权限、资源使用等信息,在开发插件时,程序入口和权限等信息都通过Manifest进行描述,程序和资源都以Manifest所在目录为根目录进行寻址,我们所开发应用的Manifest文件如下所示。
{
"name": "Weibo Photo Eraser",
"version": "1.0.2",
// 将文件注入到主页面,matches描述了哪些页面执行注入,js和css为注入的文件列表
"content_scripts": [
{
"matches": ["https://weibo.com/*", "http://weibo.com/*"],
"js": ["js/jquery.js", "js/toastr.min.js", "js/delete.js"],
"css": ["css/toastr.min.css", "css/delete.css"]
}
],
"description": "An Extension to erase photos in weibo album waterfall.",
// 插件的权限申请,declarativeContent权限支持按站点内容匹配操作
"permissions": ["declarativeContent"],
// 插件的关于(About)页面
"options_page": "options.html",
// 后台脚本执行,可以在用户不点击扩展按钮情况下自动触发
"background": {
"scripts": [
"js/background.js"
],
// 只有包含网络请求时才置为true
"persistent": false
},
// 配置Chrome的toolbar扩展图标以及点击以后的弹出页面
"page_action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/weibo16.png",
"32": "images/weibo32.png",
"48": "images/weibo48.png",
"128": "images/weibo128.png"
}
},
// 扩展图标
"icons": {
"16": "images/weibo16.png",
"32": "images/weibo32.png",
"48": "images/weibo48.png",
"128": "images/weibo128.png"
},
// Manifest描述文件版本号,用于Chrome按照描述文件版本分析Manifest,目前最新的版本为2
"manifest_version": 2
}
复制代码
如果想要进一步了解Manifest的构成,可以查看Manifest File Format文档了解。
在上述代码中,最关键的是content_scripts
描述的代码注入,我们删除照片的逻辑是将jQuery和向主页面添加按钮的代码注入并执行,在用户点击按钮时执行删除照片的代码。
"content_scripts": [
{
"matches": ["https://weibo.com/*", "http://weibo.com/*"],
"js": ["js/jquery.js", "js/toastr.min.js", "js/delete.js"],
"css": ["css/toastr.min.css", "css/delete.css"]
}
]
复制代码
这里描述了针对weibo.com
站点的代码注入,注入内容包含了jQuery库、Toastr库(用于展示全局Toast提示框)以及我们自己的逻辑代码delete.js
,数组中的文件是按顺序依次引入的,并且以Manifest所在目录为根目录寻址,因此需要注意文件路径以及按照依赖关系调整引入顺序。
在delete.js
中,我们通过jQuery添加一个按钮,并在按钮的点击事件监听函数内执行删除顶部照片的操作。
$('body').prepend('')
$('#delete-btn-c').click(() => {
let $modules = $('.photo_module');
let len = $modules.length;
if (len < 30) {
toastr.warning('Photos are too few(less than 30), do not need to remove.');
return;
}
for (let i = 0; i < len - 20; i++) {
$modules[i].remove();
}
toastr.info('Successfully removed ' + (len - 20) + ' photos');
});
复制代码
这里用到了阿里的iconfont来显示按钮图标,所引入的按钮样式以及iconfont注册信息在上面注入的delete.css
中定义。
@font-face {
font-family: 'iconfont';
src: url('//at.alicdn.com/t/font_***.eot');
src: url('//at.alicdn.com/t/font_***.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_***.woff') format('woff'),
url('//at.alicdn.com/t/font_***.ttf') format('truetype'),
url('//at.alicdn.com/t/font_***.svg#iconfont') format('svg');
}
.iconfont {
font-family: 'iconfont';
font-size: 20px;
}
#delete-btn-c {
display: block;
position: fixed;
width: 40px;
height: 40px;
border-radius: 20px;
background-color:#907a64;
user-select: none;
opacity: 0.8;
right: 12px;
bottom: 120px;
z-index: 10000;
text-align: center;
line-height: 40px;
color: white;
font-size: 16px;
}
复制代码
通过上述文件,已经可以实现通过点击按钮触发照片墙顶部的图片移除,除此之外,background.js
中所做的事情是在weibo.com
站点点亮扩展图标,options_page
配置了插件的关于(About)页面的逻辑,page_action
则配置了弹出页面的逻辑,与本文要实现的目的关系不大,这里不再赘述,相关的内容可以参考GitHub上的插件源码,github.com/Soulghost/W…。
效果演示
参考资料
developer.chrome.com/extensions