以下是一个适合小团队自用的 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(), // 用时间戳作为唯一 idcontent,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)。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93694.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93694.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93694.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Redis数据库开启SSL加密】【小白指南】【生产环境可用】附带Docker服务器配置和python连接Redis数据库代码(加密通讯版)

【Redis数据库开启SSL加密】【填坑指南】附带服务器配置和python连接测试代码 本教程转为小白提供设置Redis安全访问&#xff0c;自签名证书进行安全访问你的Redis数据库&#xff0c;轻松实现安全访问和保护数据库不被非法入侵。 本文原创&#xff0c;转载请注明出处&#xff0…

笔记本电脑键盘失灵【已解决】

配置环境硬件详情笔记本电脑联想拯救者y7000 2019 PG0&#xff08;已更新为win11&#xff09;外接键盘colorful ckb-p100问题今天笔记本开机后&#xff0c;进入登录页面输入密码&#xff0c;突然发现笔记本自带键盘&#xff08;我通常不用外接键盘&#xff09;的键失灵了&#…

postgresql运维问题解决:PG集群备节点状态异常告警处理

小亦平台会持续给大家科普一些运维过程中常见的问题解决案例&#xff0c;运维朋友们可以在常见问题及解决方案专栏查看更多案例 问题概述&#xff1a; 故障&#xff1a; pg数据库备节点状态异常现象&#xff1a; 一般为集群间心跳超时导致,现象为集群有fail-count失败数告警&…

Maven 开发实践

文章目录1. 搭建私服&#xff08;windows)2.上传依赖3.多个远程仓库配置4.其它1. 搭建私服&#xff08;windows) 软件下载 https://help.sonatype.com/en/download.html修改端口 etc/nexus-default.properties启动程序 管理员身份进入进入bin目录下执行.\nexus.exe /run创建Ma…

设计心得——如何架构选型

一、架构的作用 可能对于很多的公司&#xff0c;其实架构本身的重要性并不大。大家一定明白这回事&#xff0c;架构在实际的开发&#xff0c;在大多数的场景下其实用处并没有书籍和资料中讲的那样重要&#xff0c;甚至是可有可无。这样讲是不有些可笑&#xff1f;是不是觉得挺意…

vba学习系列(12)--反射率通过率计算复杂度优化25/8/17

系列文章目录 文章目录系列文章目录前言一、反射率通过率1.整体通过率2.整体通过率3.客户工艺匹配4.机台通过率分析5.镜片通过率罩次分析分析1.1分析1.26.镜片通过率圈数分析分析1.1分析1.28.镜筒通过率圈数分析分析1.1分析1.29.镜筒通过率罩次分析分析1.2总结前言 一、反射率通…

Microsoft WebView2

运行效果 代码如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Form…

GitCode 疑难问题诊疗:全方位指南

一、问题诊断与解决框架1.1 通用问题排查流程在面对 GitCode 问题时&#xff0c;遵循一套科学的排查流程至关重要。首先&#xff0c;详细记录问题出现时的具体操作步骤与相关报错信息&#xff0c;这有助于精准定位问题根源。例如&#xff0c;若在执行git push命令时出现错误&am…

AMD Ryzen AI Max+ 395四机并联:大语言模型集群推理深度测试

本文介绍使用四块Framework主板构建AI推理集群的完整过程&#xff0c;并对其在大语言模型推理任务中的性能表现进行了系统性评估。该集群基于AMD Ryzen AI Max 395处理器&#xff0c;采用mini ITX规格设计&#xff0c;可部署在10英寸标准机架中。 Jeff Geerling大佬还开发了名…

深度学习·GFSS

GFSS General Few-Shot Segmentation 任务实现方式与zero-shot有所不同本篇论文只涉及同一个模态(图像)&#xff0c;训练过程中&#xff0c;novel class有几个图像提供&#xff0c;提供k个就称之为k-shot。先从图像中提取class prototype&#xff0c;然后这个原型向量作为查询&…

Transformer架构的数学本质:从注意力机制到大模型时代的技术内核

系列专栏推荐&#xff1a;零基础学Python&#xff1a;Python从0到100最新最全教程 深入浅出讲解神经网络原理与实现&#xff0c;从基础的多层感知机到前沿的Transformer架构。包含完整的数学推导、代码实现和工程优化技巧。 写在前面&#xff1a;为什么理解Transformer如此重要…

最新微信小程序一键获取真实微信头像和昵称方法

使用公开免费插件&#xff0c;快速实现获取用户头像和昵称&#xff0c;已附uniapp、微信开发工具开发详细教程。前言为了保护用户隐私&#xff0c;wx.getUserInfo、wx.getUserProfile都没法获取到用户头像和昵称了&#xff0c;只能通过设计用户主动选择/输入形式&#xff0c;操…

路由器配置之模式

文章目录配置路由器时&#xff0c;有一个模式选择最佳实践各个选项的区别11b only11g only11n only11bg mixed11bgn mixed配置路由器时&#xff0c;有一个模式选择 最佳实践 • 追求速度&#xff1a;选 11n only&#xff08;需所有设备支持&#xff09;。 • 兼容性优先&…

评测系统构建

合成数据更“科研驱动”&#xff0c;强调 controllability 和 generalization evaluation&#xff1a; 之前往往直接采用经典数据集如OGB和OGB-large提供的经典数据集和数据划分思路 该思想从现有真实数据中学习参数&#xff0c;再构造类似但分布略异的数据集&#xff0c;验证模…

【计算机网络面试】TCP/IP网络模型有哪几层

参考&#xff1a; 2.1 TCP/IP 网络模型有哪几层&#xff1f; | 小林coding | Java面试学习 以下为自己做的笔记 应用层 专注于为用户提供应用功能&#xff0c;如HTTP、FTP、Telnet、DNS、SMTP等。应用层不关心用户是怎么传输的&#xff0c;当两个设备间的应用需要通信时&…

3 种方式玩转网络继电器!W55MH32 实现网页 + 阿里云 + 本地控制互通

目录 1 前言 2 项目环境 2.1 硬件准备 2.2 软件准备 2.3 方案图示 3 例程修改 4 功能验证 5. 总结 1 前言 HTTP&#xff08;超文本传输协议&#xff0c;HyperText Transfer Protocol&#xff09;是一种用于分布式、协作式、超媒体信息系统的应用层协议&#xff0c; 基于 TCP/IP…

第四篇:科技封锁与文化渗透篇——T-501 与 M-208 双引擎布局(节奏增强版)

科技封锁与文化渗透篇——T-501 与 M-208 双引擎布局&#xff08;节奏增强版&#xff09; 引子 在全球竞争中&#xff0c;光有资本和市场远远不够。 • 科技封锁&#xff08;T-501&#xff09;&#xff1a;通过技术标准、专利网络、供应链控制&#xff0c;让对手进入成本极高的…

python实现梅尔频率倒谱系数(MFCC) 除了傅里叶变换和离散余弦变换

语音识别第4讲&#xff1a;语音特征参数MFCC https://zhuanlan.zhihu.com/p/88625876/ Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What’s In-Between https://haythamfayek.com/2016/04/21/speech-processing-…

springBoot+knife4j+openapi3依赖问题参考

pom文件附带版本<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.12</version></parent><dependencies><!-- SpringDoc starter --><d…

XML DOM 高级

XML DOM 高级 引言 XML DOM(Document Object Model)是用于解析和操作XML文档的一种标准,它允许开发者通过编程方式访问和修改XML文档的内容。本文将深入探讨XML DOM的高级特性,包括XML解析、节点操作、事件处理以及性能优化等,帮助读者全面理解并掌握XML DOM的高级应用。…