以下是一个适合小团队自用的 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); // 保存后重新渲染
});
}
三、测试与使用
- 准备图标:临时找 3 个尺寸的图标(或用在线工具生成),命名为
icon-16.png
、icon-48.png
、icon-128.png
放入项目目录。 - 加载插件:
- 打开 Chrome 浏览器,进入
chrome://extensions
。 - 开启右上角「开发者模式」→ 点击「加载已解压的扩展程序」→ 选择项目目录
todo-list-extension
。
- 打开 Chrome 浏览器,进入
- 使用插件:
- 点击浏览器右上角的插件图标,弹出 TodoList 界面。
- 输入任务内容,点击「添加」或按回车键添加任务。
- 勾选复选框标记任务完成(文字会划线),点击「×」删除任务。
- 关闭插件后重新打开,数据会保留(本地存储)。
四、扩展方向(小团队可能需要)
- 任务分类/标签:添加「工作」「生活」等标签,按分类筛选任务。
- 截止日期提醒:为任务添加截止时间,到期前弹出通知(需
alarms
权限)。 - 团队共享:结合团队协作工具(如飞书、Trello API)同步任务(需后端服务)。
- 数据备份:添加「导出/导入」功能,支持 JSON 文件备份(用
chrome.downloads
API)。
这个示例实现了小团队最核心的任务管理需求,代码简洁易扩展,适合作为团队内部工具快速落地。