功能概述

为了更方便使用 Chrome 我设一款插件来解决日常浏览器标签页管理的痛点。今天分享一下他的侧边栏的功能。FunTester 侧边栏的核心功能包括标签页管理、主题切换、标签页操作、右键菜单、交互优化和消息监听。通过显示当前窗口的所有标签页并支持按域名分组与排序,我希望帮助用户更高效地管理标签页。同时,插件提供深色和浅色主题切换功能,满足不同用户的视觉偏好。

由于不可描述的原因,无法开源,有需求交流的小伙伴私聊,后续会有视频展示这些功能。

此外,用户可以通过插件执行多种标签页操作,例如刷新、创建新标签页,以及检查并打开指定 URL 的标签页。自定义右键菜单进一步增强了操作的灵活性,支持复制 URL、关闭标签页等功能。动态加载标签页图标和实时更新标签页状态(如静音状态)优化了用户的交互体验。最后,通过监听来自扩展的消息并执行相应操作,我让插件实现了与用户的实时交互。这些功能的结合使得插件在提供便捷的标签页管理体验的同时,也提升了用户操作的效率和灵活性。

功能实现设计与细节

标签页管理

标签页列表展示

在实现标签页列表展示时,我使用了 ul 元素动态生成标签页列表。每个标签页以 li 元素表示,标签页的标题、URL 和图标通过 DOM 操作动态插入,确保内容实时更新,提升用户体验。

const list = document.getElementById('tabs-list'); // 获取标签页列表的容器

function createTab(tab) {
  const listItem = document.createElement('li'); // 创建列表项
  listItem.id = tab.id; // 设置列表项的 ID 为标签页 ID
  listItem.style.color = getItemColor(); // 设置文本颜色
  listItem.style.backgroundColor = getItemBackgroundColor(); // 设置背景颜色
  const link = document.createElement('a'); // 创建链接元素
  link.textContent = tab.title || tab.url; // 设置链接文本为标签页标题或 URL
  link.style.color = getLinkColor(); // 设置链接颜色
  const icon = createIcon(tab); // 创建标签页图标
  listItem.appendChild(icon); // 将图标添加到列表项
  listItem.appendChild(link); // 将链接添加到列表项
  list.appendChild(listItem); // 将列表项添加到列表容器
}

按域名分组和排序

为了让标签页展示更加清晰有序,我使用了 Array.prototype.reduce 方法将标签页按域名分组,并生成一个以域名为键的对象。随后,通过对域名键进行字母顺序排序,确保分组后的标签页展示更加清晰有序。

function sortTabs(tabs) {
  const tabsByDomain = tabs.reduce((acc, tab) => {
    const domain = new URL(tab.url).hostname; // 提取标签页的域名
    if (!acc[domain]) {
      acc[domain] = []; // 如果域名不存在,初始化为空数组
    }
    acc[domain].push(tab); // 将标签页添加到对应域名的数组中
    return acc;
  }, {});
  return Object.keys(tabsByDomain) // 获取所有域名
    .sort() // 按字母顺序排序域名
    .map(domain => tabsByDomain[domain]); // 返回排序后的标签页数组
}

主题切换

实现方式

在主题切换功能中,我定义了深色和浅色主题的颜色变量(如 colorWhitecolorBlack)。通过按钮点击事件切换 isDarkTheme 状态,并动态更新页面样式。

const toggleThemeButton = document.getElementById('toggleTheme'); // 获取主题切换按钮
let isDarkTheme = false; // 初始化主题状态为浅色

function getItemColor() {
  return isDarkTheme ? '#ffffff' : '#000000'; // 根据主题返回文本颜色
}

function getItemBackgroundColor() {
  return isDarkTheme ? '#333333' : '#ffffff'; // 根据主题返回背景颜色
}

toggleThemeButton.addEventListener('click', () => {
  isDarkTheme = !isDarkTheme; // 切换主题状态
  document.body.style.backgroundColor = getItemBackgroundColor(); // 更新页面背景颜色
});

标签页操作

刷新标签页

为了让用户能够快速更新页面内容,我通过调用 chrome.tabs.reload 方法实现了刷新当前标签页和所有标签页的功能。用户可以通过点击按钮选择刷新当前活动标签页,或遍历所有标签页并逐一刷新。

document.getElementById('reloadTabs').addEventListener('click', function () {
  chrome.tabs.query({ currentWindow: true }, function (tabs) {
    tabs.forEach(tab => chrome.tabs.reload(tab.id)); // 遍历当前窗口的所有标签页并刷新
  });
});

创建新标签页

通过调用 chrome.tabs.create 方法,我实现了创建新标签页的功能。用户点击按钮后,插件会打开一个新的空白标签页或指定 URL 的标签页。

document.getElementById('createNewTab').addEventListener('click', function () {
  chrome.tabs.create({ url: 'about:blank' }); // 创建一个新的空白标签页
});

检查并打开指定 URL

为了避免重复打开相同的页面,我通过 chrome.tabs.query 方法检查当前窗口是否已打开指定 URL 的标签页。若存在,则调用 chrome.tabs.update 激活该标签页;若不存在,则调用 chrome.tabs.create 新建标签页并打开指定 URL。

function checkAndOpen(url) {
  chrome.tabs.query({ currentWindow: true }, function (tabs) {
    const existingTab = tabs.find(tab => tab.url === url); // 查找是否存在指定 URL 的标签页
    if (existingTab) {
      chrome.tabs.update(existingTab.id, { active: true }); // 如果存在,激活该标签页
    } else {
      chrome.tabs.create({ url: url }); // 如果不存在,创建新标签页并打开 URL
    }
  });
}

右键菜单

自定义菜单

右键菜单是插件的一大亮点。我通过动态创建右键菜单 DOM 元素实现了这一功能。菜单包含复制 URL复制并新标签页打开关闭标签页等选项。

function createContextMenu() {
  const menu = document.createElement('div'); // 创建菜单容器
  menu.id = 'custom-context-menu'; // 设置菜单 ID
  const ul = document.createElement('ul'); // 创建菜单列表

  const copyUrlItem = document.createElement('li'); // 创建“复制 URL”菜单项
  copyUrlItem.textContent = '复制 URL'; // 设置菜单项文本
  copyUrlItem.addEventListener('click', () => {
    navigator.clipboard.writeText(currentCopyUrl); // 将当前 URL 复制到剪贴板
  });

  ul.appendChild(copyUrlItem); // 将菜单项添加到菜单列表
  menu.appendChild(ul); // 将菜单列表添加到菜单容器
  document.body.appendChild(menu); // 将菜单容器添加到页面
}

交互优化

标签页图标

为了提升界面美观与一致性,我通过动态创建 img 元素加载标签页图标,优先使用网站 favicon,无则用默认图标。

function createIcon(tab) {
  const icon = document.createElement('img'); // 创建图标元素
  icon.src = tab.favIconUrl || 'default-icon.png'; // 设置图标 URL,若无图标则使用默认图标
  icon.style.width = '20px'; // 设置图标宽度
  icon.style.height = '20px'; // 设置图标高度
  return icon; // 返回图标元素
}

标签页状态更新

通过监听 chrome.tabs.onUpdated 事件,我实现了标签页状态的即时反馈和交互优化。

chrome.tabs.onUpdated.addListener((id, changeInfo, tab) => {
  if (changeInfo.mutedInfo) {
    const muteBtn = document.getElementById(`${id}-mute-btn`); // 获取静音按钮
    muteBtn.style.backgroundColor = tab.mutedInfo.muted ? '#32CD32' : '#1E90FF'; // 根据静音状态更新按钮颜色
  }
});

设计亮点

模块化设计是这款插件的一大亮点。通过将各项功能拆分为独立的函数模块,不仅提高了代码的可读性,还便于后续的维护和功能扩展。例如,标签页管理、主题切换、右键菜单等功能均通过单独的函数实现,确保了代码结构的清晰性和功能的独立性。

动态交互的实现进一步提升了用户体验。插件通过事件监听和 DOM 操作实现了实时的界面更新,例如标签页状态的动态变化和右键菜单的交互响应。这种实时性和动态性使得用户能够感受到操作的即时反馈,从而增强了使用的流畅性和便捷性。

主题切换功能为用户提供了深色和浅色两种视觉模式,满足了不同用户的偏好需求。通过简单的按钮点击,用户即可在两种主题之间切换,页面的颜色和样式会随之动态更新。这种设计不仅提升了用户的视觉舒适度,还增强了插件的个性化体验。

自定义右键菜单是插件功能灵活性的体现。用户可以通过右键菜单快速执行诸如复制 URL、关闭标签页等操作,避免了繁琐的步骤。右键菜单的动态生成和事件绑定确保了功能的扩展性,同时也为用户提供了更加高效的操作方式。


FunTester 原创精华


↙↙↙阅读原文可查看相关链接,并与作者交流