创建标签页管理器
概述
实现功能:
- 自动检测并显示所有打开的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:这里为什么要排序?
- 用户体验优化:按标题字母排序,更容易找到,展示方式更有组织性
- 使用
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. 加载扩展
- 打开Chrome浏览器
- 访问
chrome://extensions/
- 开启"开发者模式"
- 点击"加载已解压的扩展程序"
- 选择项目目录
实现效果:
完整示例代码👇