阅读 418

通过开发Chrome插件解决浏览器查看微博照片墙的页面卡顿

背景

相信大家都会有类似的经历,当我们在浏览微博查看他人的照片墙时,在我们不断向下滑动查看照片的过程中,照片墙上方的图片不会被清除,当查看的照片过多时,页面会明显变卡,在这种情况下,笔者常常通过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('<a id="delete-btn-c"><i class="iconfont">&#xe673;</i></a>')
$('#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

文章分类
前端