手摸手教你写个chrome插件

423 阅读5分钟

目录

  1. 需求分析
  2. 官网Demo入门
  3. Manifest配置文件
  4. 实现思路
  5. 核心代码
  6. 实现效果

不知道大家有没有过类似的经历,查阅资料时经常会打开一堆临时tab标签,不至于到要加入收藏夹的地步,但是直接关了再找又麻烦,而且挤挤挨挨的一堆找起来也很费眼睛......

密密麻麻的tab标签页

有没有什么工具能保存下我打开的tab,并且能方便地查看?

受到印象笔记剪藏插件的启发,我找到了个插件OneTab,可以一键关闭所有标签页并保存到一个页面中:

OneTab

出于好奇,我去了解了下:如何写一个chrome插件?

再次打开一堆tab.......

写一个chrome插件需要的技术基础:html、js、css

???就这?这不就是我前端切图仔的三板斧吗?!

话不多说,直接开撸!

需求分析

首先分析我的需求:

  1. 保存打开的网页地址;
  2. 看完后可以便捷地删除;
  3. 最好能一键全部保存;
  4. 再来个一键删除;
  5. 再来个一键全开;

......

打住打住,先完成核心需求再说= =。

官网Demo入门

依据官网上的指示,插件应包含以下文件:

  • 一个manifest文件(配置文件)
  • 一个或多个HTML文件(除非这个应用是一个皮肤)
  • 可选的一个或多个JavaScript文件
  • 可选的任何需要的其他文件,例如图片

除了manifest不知道是啥,其他都是熟悉的配方。谷歌官方还很贴心地给出了入门demo:storage.googleapis.com/chrome-gcs-…

下载下来后可以看到有这么几个文件:

getting-started目录

打开chrome,右上角扩展操作>更多工具>扩展程序,点击加载已解压的扩展程序,选中上面的文件夹,就可以看到加载进来的demo插件。

加载插件

已加载进来的demo插件

Manifest配置文件

我们先来看看demo里的manifest.json配置:

{
  "name": "Getting Started Example",
  "description": "Build an Extension!",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "permissions": ["storage", "activeTab", "scripting"],
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "/images/get_started16.png",
      "32": "/images/get_started32.png",
      "48": "/images/get_started48.png",
      "128": "/images/get_started128.png"
    }
  },
  "icons": {
    "16": "/images/get_started16.png",
    "32": "/images/get_started32.png",
    "48": "/images/get_started48.png",
    "128": "/images/get_started128.png"
  },
  "options_page": "options.html"
}

配置说明

参数说明
name插件名称
description插件描述
version插件版本号
manifest_version清单文件的版本(目前是3,按照官方的来就可以)
background后台默认程序,版本3使用service_worker替代了之前的scripts,主要作用是管理缓存、预加载资源和启用离线网页。
permissions需要的权限
actiontoolbar扩展菜单配置
icons插件图标(可以适配不同的尺寸)
options_page扩展程序选项(一般是让用户自定义选择插件的某些参数值)

其中,

  • 本次需要的permissions有:
  • action这里我用的是清单版本2中的browser_action,版本3中的action无法弹出popup选项卡,估计是我用的姿势不太对......(有知道的童鞋可以留言告诉我怎么用~)

修改后的配置文件:

{
    "manifest_version": 3,
    "name": "阅读TODO清单",
    "version": "1.0.0",
    "description": "一键保存tab,轻松管理临时标签页",
    "icons":
    {
        "16": "images/icon.png",
        "48": "images/icon.png",
        "128": "images/icon.png"
    },
    "browser_action":
    {
        "default_icon": "images/icon.png",
        "default_title": "阅读清单-by 游走走",
        "default_popup": "popup.html"
    },
    "permissions":
    [
        "tabs",
        "storage",
        "unlimitedStorage"
    ],
    "options_page": "options.html",
    "homepage_url": "https://github.com/youzouzou/my-chrome-plugin-read-todo"
}
  • homepage_url:扩展程序网站,这里指向了我的github开源地址:)

实现思路

TODO清单这种小玩意儿就不多说了,简单来讲就是维护一个数组,并通过本地缓存get/set来实现增删改查。

核心代码

popup插件选项卡

讲完了配置,接下来就是我们熟悉的html/js/css三板斧了。

popup.html里我定义了三个按钮:加入阅读清单查看清单加入所有打开tab

<div id="addBtn">加入阅读清单</div>
<div id="viewBtn">查看清单</div>
<div id="addAll">加入所有打开tab</div>

监听按钮点击事件:

const addBtn = document.getElementById("addBtn")
addBtn.addEventListener("click", async () => { });

加入阅读清单

加入阅读清单是将当前tab的url和title保存到缓存数组中,这里就涉及到3个chrome的API。

  1. 获取当前tab的url和title
chrome.tabs.getSelected(null, function (tab) {
  console.log(tab.url, tab.title)
});
  1. 获取当前缓存的tab数组
chrome.storage.sync.get("tabs", ({ tabs }) => { });
  1. 更新缓存中的tab数组
chrome.storage.sync.set({ "tabs": newTabList });

查看清单

viewBtn.addEventListener("click", async () => {
  window.open(chrome.extension.getURL('list.html'));
});

这里会打开一个新的tab页,指向的是list.html文件。我在这个页面展示了缓存的tab数组,并提供了单个url打开/删除、一键全部打开/删除的功能。

加入所有打开tab

这里和加入单个tab差不多,只不过需要多调一个API来获取所有窗口的所有tab:

chrome.windows.getAll({ populate: true }, function (windows) {
      windows.forEach(function (window) {
        window.tabs.forEach(function (tab) {
          // 遍历到所有tab
        });
      });
});

核心代码基本就是这几个API,具体实现可以参照demo:github.com/youzouzou/m…

感兴趣的同学可以下载demo,加载已解压的扩展程序,就可以看到具体的实现效果。打包成.crx文件也很简单,打开扩展程序,点击打包扩展程序

打包扩展程序

还可以注册开发者账号,将开发好的插件上传到chrome网上应用商店供其他用户购买和下载(发家致富的路子又多了一个有木有~)。

实现效果

chrome插件展示

左键点击toolbar中的插件

右键点击toolbar中的插件

注:这里的阅读TODO清单指向的就是homepage_url选项指向的就是options_page

查看清单

总结

功能比起OneTab是要简陋得多,不过通过这次尝试,打开了我新世界的大门,以后解决问题的思路又多了一种√。