Chrome插件开发实战:todoList 插件

发布于:2025-08-18 ⋅ 阅读:(13) ⋅ 点赞:(0)

以下是一个适合小团队自用的 Chrome TodoList 插件开发示例,包含基础功能(增删改查、本地存储、统计)和简洁的交互设计。代码结构清晰,适合新手学习或快速上手。

在这里插入图片描述

一、项目准备

创建插件项目目录 todo-list-extension,包含以下文件:

todo-list-extension/
├── manifest.json   # 插件配置文件
├── popup.html      # 弹出页面
├── popup.css       # 样式文件
└── popup.js        # 逻辑脚本

二、核心代码实现

1. manifest.json(插件配置)
{
  "manifest_version": 3,
  "name": "小团队 TodoList",
  "version": "1.0.0",
  "description": "小团队自用的任务管理工具,数据本地持久化",
  "icons": {
    "16": "icon-16.png",
    "48": "icon-48.png",
    "128": "icon-128.png"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icon-16.png",
      "48": "icon-48.png",
      "128": "icon-128.png"
    }
  },
  "permissions": ["storage"], // 使用本地存储需要此权限
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'"
  }
}

说明

  • manifest_version: 3 是 Chrome 推荐的最新版本,更安全高效。
  • permissions: ["storage"] 用于访问本地存储(chrome.storage.local)。
  • 需准备 16x16、48x48、128x128 的图标(可临时用占位图)。
2. popup.html(弹出页面结构)
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <link rel="stylesheet" href="popup.css">
</head>
<body>
  <div class="container">
    <!-- 统计栏 -->
    <div class="stats">
      <span>总任务:<span id="total">0</span></span>
      <span>已完成:<span id="completed">0</span></span>
    </div>

    <!-- 添加任务表单 -->
    <div class="add-task">
      <input 
        type="text" 
        id="taskInput" 
        placeholder="输入新任务(回车添加)"
        autocomplete="off"
      >
      <button id="addBtn">添加</button>
    </div>

    <!-- 任务列表 -->
    <ul id="taskList"></ul>
  </div>
  <script src="popup.js"></script>
</body>
</html>
3. popup.css(样式美化)
body {
  width: 350px;
  min-height: 400px;
  margin: 0;
  padding: 15px;
  font-family: 'Segoe UI', sans-serif;
  background: #f5f7fa;
}

.container {
  max-width: 100%;
}

.stats {
  color: #666;
  font-size: 12px;
  margin-bottom: 15px;
  display: flex;
  gap: 15px;
}

.add-task {
  display: flex;
  gap: 8px;
  margin-bottom: 15px;
}

#taskInput {
  flex: 1;
  padding: 8px 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  outline: none;
}

#taskInput:focus {
  border-color: #4a90e2;
  box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.1);
}

#addBtn {
  padding: 8px 16px;
  background: #4a90e2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background 0.2s;
}

#addBtn:hover {
  background: #357abd;
}

#taskList {
  list-style: none;
  padding: 0;
  margin: 0;
}

.task-item {
  display: flex;
  align-items: center;
  padding: 10px;
  background: white;
  border-radius: 4px;
  margin-bottom: 8px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  transition: transform 0.1s;
}

.task-item:hover {
  transform: translateX(5px);
}

.task-checkbox {
  width: 18px;
  height: 18px;
  margin-right: 12px;
  cursor: pointer;
}

.task-content {
  flex: 1;
  font-size: 14px;
  color: #333;
}

.task-content.completed {
  text-decoration: line-through;
  color: #999;
}

.delete-btn {
  color: #ff4d4f;
  background: none;
  border: none;
  cursor: pointer;
  font-size: 16px;
  opacity: 0.7;
  transition: opacity 0.2s;
}

.delete-btn:hover {
  opacity: 1;
}
4. popup.js(核心逻辑)
// 初始化:加载本地存储的任务
document.addEventListener('DOMContentLoaded', () => {
  loadTasks();
  renderTasks();
});

// 获取 DOM 元素
const taskInput = document.getElementById('taskInput');
const addBtn = document.getElementById('addBtn');
const taskList = document.getElementById('taskList');
const totalEl = document.getElementById('total');
const completedEl = document.getElementById('completed');

// 添加任务(按钮点击或回车)
addBtn.addEventListener('click', addTask);
taskInput.addEventListener('keypress', (e) => {
  if (e.key === 'Enter') addTask();
});

// 加载本地存储的任务
function loadTasks() {
  chrome.storage.local.get(['tasks'], (result) => {
    const tasks = result.tasks || [];
    renderTasks(tasks);
  });
}

// 渲染任务列表
function renderTasks(tasks = []) {
  // 清空旧列表
  taskList.innerHTML = '';

  // 统计数据
  const total = tasks.length;
  const completed = tasks.filter(t => t.completed).length;
  totalEl.textContent = total;
  completedEl.textContent = completed;

  // 渲染每个任务
  tasks.forEach(task => {
    const li = document.createElement('li');
    li.className = 'task-item';
    li.dataset.id = task.id; // 用 id 标识任务

    li.innerHTML = `
      <input 
        type="checkbox" 
        class="task-checkbox" 
        ${task.completed ? 'checked' : ''}
      >
      <span class="task-content ${task.completed ? 'completed' : ''}">
        ${task.content}
      </span>
      <button class="delete-btn">×</button>
    `;

    // 绑定复选框事件(标记完成/未完成)
    const checkbox = li.querySelector('.task-checkbox');
    checkbox.addEventListener('change', () => toggleTask(task.id));

    // 绑定删除按钮事件
    const deleteBtn = li.querySelector('.delete-btn');
    deleteBtn.addEventListener('click', () => deleteTask(task.id));

    taskList.appendChild(li);
  });
}

// 添加新任务
function addTask() {
  const content = taskInput.value.trim();
  if (!content) return; // 空任务不添加

  const newTask = {
    id: Date.now(), // 用时间戳作为唯一 id
    content,
    completed: false,
    createdAt: new Date().toISOString()
  };

  // 读取现有任务并追加新任务
  chrome.storage.local.get(['tasks'], (result) => {
    const tasks = result.tasks || [];
    tasks.push(newTask);
    saveTasks(tasks); // 保存到本地存储
    taskInput.value = ''; // 清空输入框
  });
}

// 切换任务完成状态
function toggleTask(taskId) {
  chrome.storage.local.get(['tasks'], (result) => {
    const tasks = result.tasks || [];
    const index = tasks.findIndex(t => t.id === taskId);
    if (index !== -1) {
      tasks[index].completed = !tasks[index].completed;
      saveTasks(tasks);
    }
  });
}

// 删除任务
function deleteTask(taskId) {
  chrome.storage.local.get(['tasks'], (result) => {
    const tasks = result.tasks || [];
    const filtered = tasks.filter(t => t.id !== taskId);
    saveTasks(filtered);
  });
}

// 保存任务到本地存储
function saveTasks(tasks) {
  chrome.storage.local.set({ tasks }, () => {
    renderTasks(tasks); // 保存后重新渲染
  });
}

在这里插入图片描述

三、测试与使用

  1. 准备图标:临时找 3 个尺寸的图标(或用在线工具生成),命名为 icon-16.pngicon-48.pngicon-128.png 放入项目目录。
  2. 加载插件
    • 打开 Chrome 浏览器,进入 chrome://extensions
    • 开启右上角「开发者模式」→ 点击「加载已解压的扩展程序」→ 选择项目目录 todo-list-extension
  3. 使用插件
    • 点击浏览器右上角的插件图标,弹出 TodoList 界面。
    • 输入任务内容,点击「添加」或按回车键添加任务。
    • 勾选复选框标记任务完成(文字会划线),点击「×」删除任务。
    • 关闭插件后重新打开,数据会保留(本地存储)。

四、扩展方向(小团队可能需要)

  1. 任务分类/标签:添加「工作」「生活」等标签,按分类筛选任务。
  2. 截止日期提醒:为任务添加截止时间,到期前弹出通知(需 alarms 权限)。
  3. 团队共享:结合团队协作工具(如飞书、Trello API)同步任务(需后端服务)。
  4. 数据备份:添加「导出/导入」功能,支持 JSON 文件备份(用 chrome.downloads API)。

这个示例实现了小团队最核心的任务管理需求,代码简洁易扩展,适合作为团队内部工具快速落地。


网站公告

今日签到

点亮在社区的每一天
去签到