跳到主要内容

创建标签页管理器

概述

实现功能:

  • 自动检测并显示所有打开的Chrome开发者文档标签页
  • 按标题对标签页进行排序
  • 提供一键分组功能
  • 点击标签页可以快速切换到对应页面

教程

1. 创建项目结构

首先创建以下文件结构:

tabs-manager/
├── manifest.json
├── popup.html
├── popup.css
├── popup.js
└── images/
├── icon-16.png
├── icon-32.png
├── icon-48.png
└── icon-128.png

2. 配置manifest.json

创建manifest.json文件,这是Chrome扩展的配置文件:

{
"manifest_version": 3,
"name": "Tab Manager for Chrome Dev Docs",
"version": "1.0",
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"action": {
"default_popup": "popup.html"
},
"host_permissions": [
"https://developer.chrome.com/"
],
"permissions": [
"tabGroups"
]
}

说明:

  • action:定义扩展在 Chrome 工具栏中的行为,这里的 default_popup 指定了点击扩展图标打开时的 HTML 文件
  • host_permissions:声明扩展需要访问的网站域名
  • permissions:声明扩展需要的 Chrome API 权限

3. 创建popup.html

创建扩展的弹出窗口界面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./popup.css" />
</head>
<body>
<template id="li_template">
<li>
<a>
<h3 class="title">Tab Title</h3>
<p class="pathname">Tab Pathname</p>
</a>
</li>
</template>

<h1>Google Dev Docs</h1>
<button>Group Tabs</button>
<ul></ul>

<script src="./popup.js" type="module"></script>
</body>
</html>

说明:

  • 这里的 html 使用了 template 标签,这是一个 HTML5 的一个很有用的元素,可以用来存储 HTML 模板,而模板中的内容在页面加载时不会被渲染,可以被 JS 克隆和重复使用(见下面 JS 部分)

4. 添加样式(popup.css)

为弹出窗口添加样式:

body {
width: 20rem;
}

ul {
list-style-type: none;
padding-inline-start: 0;
margin: 1rem 0;
}

li {
padding: 0.25rem;
}
li:nth-child(odd) {
background: #80808030;
}
li:nth-child(even) {
background: #ffffff;
}

h3,
p {
margin: 0;
}

5. 实现功能逻辑(popup.js)

创建主要的JavaScript逻辑:

// P1
const tabs = await chrome.tabs.query({
url: ['https://developer.chrome.com/docs/webstore/*', 'https://developer.chrome.com/docs/extensions/*'],
});

// P2
const collator = new Intl.Collator();
tabs.sort((a, b) => collator.compare(a.title, b.title));

// P3
const template = document.getElementById('li_template');

// P4
const elements = new Set();

// P5
for (const tab of tabs) {
const element = template.content.firstElementChild.cloneNode(true);

const title = tab.title.split('-')[0].trim();
const pathname = new URL(tab.url).pathname.slice('/docs'.length);

element.querySelector('.title').textContent = title;
element.querySelector('.pathname').textContent = pathname;
element.querySelector('a').addEventListener('click', async () => {
await chrome.tabs.update(tab.id, { active: true });
await chrome.windows.update(tab.windowId, { focused: true });
});

elements.add(element);
}
document.querySelector('ul').append(...elements);

// P7
const button = document.querySelector('button');
button.addEventListener('click', async () => {
const tabIds = tabs.map(({ id }) => id);
if (tabIds.length) {
const group = await chrome.tabs.group({ tabIds });
await chrome.tabGroups.update(group, { title: 'DOCS' });
}
});

实现技术细节:

P2:这里为什么要排序?

  1. 用户体验优化:按标题字母排序,更容易找到,展示方式更有组织性
  2. 使用 Intl.Collator 而不是简单的字符串比较,是因为它支持不同语言的排序规则

P5:这里对应了上面的 HTML 模板标签语法,因为默认不渲染,构建好被浏览器解析一次就行,有利于提高性能

实现思路流程图:

flowchart TD
A[开始] --> B[查询Chrome开发者文档标签页]
B --> C{是否有匹配的标签页?}
C -->|否| D[显示空列表]
C -->|是| E[使用Intl.Collator对标签页排序]
E --> F[获取模板元素]
F --> G[遍历标签页数组]
G --> H[克隆模板元素]
H --> I[提取标题和路径名]
I --> J[设置元素内容]
J --> K[添加点击事件监听器]
K --> L[将元素添加到Set中]
L --> M{是否还有标签页?}
M -->|是| G
M -->|否| N[将所有元素添加到UL中]
N --> O[添加分组按钮事件监听器]
O --> P[结束]

subgraph 点击事件处理
K --> K1[激活对应标签页]
K1 --> K2[聚焦对应窗口]
end

subgraph 分组按钮处理
O --> O1[获取所有标签页ID]
O1 --> O2{是否有标签页?}
O2 -->|是| O3[创建标签页组]
O3 --> O4[设置组标题为'DOCS']
O2 -->|否| O5[不执行任何操作]
end

6. 添加图标

准备四个不同尺寸的图标文件(16x16, 32x32, 48x48, 128x128),并放置在images目录下。

7. 加载扩展

  1. 打开Chrome浏览器
  2. 访问 chrome://extensions/
  3. 开启"开发者模式"
  4. 点击"加载已解压的扩展程序"
  5. 选择项目目录

实现效果:

完整示例代码👇

DEMO: chrome-extension-demos/04/tabs-manager

资源

参考