Web-Dev-For-Beginners 浏览器扩展实战:表单处理、LocalStorage 持久化与 CO2 Signal API 调用 📅 发布时间:2026/9/7 18:56:52 👁 浏览次数: Web-Dev-For-Beginners 浏览器扩展实战表单处理、LocalStorage 持久化与 CO2 Signal API 调用【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners本篇基于 Web-Dev-For-Beginners 仓库浏览器扩展模块的第 2 课5-browser-extension/2-forms-browsers-local-storage讲解如何把你已经搭好的静态表单激活注册事件监听、用 LocalStorage 记住用户配置、通过 async/await 调用 CO2 Signal API 获取某地区电网的碳排放强度并把结果渲染回扩展界面。读完并按仓库源码逐段实现后你将拥有一个能带记忆的可用扩展——用户下次打开时自动加载上次保存的 API Key 与地区数据。本课时的项目背景与代码骨架按照 5-browser-extension/README.md 的说明整个模块的目标是构建一个可在 Edge、Chrome 和 Firefox 中运行的 My Carbon Trigger 扩展它针对某个地区代码查询 CO2 Signal API返回该地区的电力使用与碳强度数据从而给出当地碳足迹读数帮助用户决定例如是否延迟烘干衣物这类用电行为。第 1 课1-about-browsers已完成扩展项目搭建、manifest 配置与 HTML 表单部分本课从这里接续。仓库为学习者提供了带编号注释的骨架文件 start/src/index.js注释块按//1到//6标出每个代码段应填入的位置——文档反复提示的✅ 按照对应文件中的编号段落放置代码即指此处//1 // form fields // results divs //6 //call the API //5 //set up users api key and region //4 // handle form submission //3 initial checks //2 // set listeners and start app从源码结构看扩展采用 Manifest V3start/dist/manifest.json 中声明了service_worker: background.js与default_popup: index.html。构建环境要求见 solution/package.jsonNode 18、npm 9依赖axios用于发请求、开发依赖 webpacknpm run build即执行webpacknpm run watch可开启监听模式。第 1 步配置要操作的 DOM 元素在第 1 课中你已经创建了表单与结果div的 HTML。从本课开始工作重心转移到/src/index.js。首先在文件顶部创建一组const变量通过 CSS 类名引用各个界面元素// form fields const form document.querySelector(.form-data); const region document.querySelector(.region-name); const apiKey document.querySelector(.api-key); // results const errors document.querySelector(.errors); const loading document.querySelector(.loading); const results document.querySelector(.result-container); const usage document.querySelector(.carbon-usage); const fossilfuel document.querySelector(.fossil-fuel); const myregion document.querySelector(.my-region); const clearBtn document.querySelector(.clear-btn);这 9 个引用分成两组表单字段.form-data、.region-name、.api-key对应上节课 HTML 中的表单容器与两个输入框结果区域.errors、.loading、.result-container、.carbon-usage、.fossil-fuel、.my-region、.clear-btn错误提示、加载状态、结果容器、碳强度读数、化石燃料占比、地区名与清除按钮。这些类名与第 1 课 HTML 中设置的一一对应。把所有引用集中在文件顶部存为const后续各函数都直接复用这些变量避免在多处重复执行querySelector查询。参考实现见 solution/src/index.js。第 2 步添加事件监听器接下来给表单和清除按钮注册事件监听器并在文件底部调用初始化函数让扩展打开时立即进入正确状态form.addEventListener(submit, (e) handleSubmit(e)); clearBtn.addEventListener(click, (e) reset(e)); init();这里值得留意两点监听器使用箭头函数简写(e) handleSubmit(e)其长格式等价写法是(e) { handleSubmit(e); }两种写法功能完全等价可按个人偏好选择事件对象e被显式传给处理函数后续函数中依赖它调用e.preventDefault()。若忘记调用表单提交将触发整页刷新丢失全部 JavaScript 状态、打断用户体验——这正是handleSubmit与reset里第一件事就是e.preventDefault()的原因。第 3 步init() 与 reset() —— LocalStorage 驱动的初始化逻辑init()决定扩展打开时展示什么如果 LocalStorage 里已有上次保存的配置就直接带数据进入老用户模式否则展示设置表单。function init() { //si hay algo en localStorage, recójalo如果 localStorage 中有数据就取出来 const storedApiKey localStorage.getItem(apiKey); const storedRegion localStorage.getItem(regionName); //establecer el icono en verde genérico把图标设为通用绿色 //todo留待后续课时实现动态图标 if (storedApiKey null || storedRegion null) { //si no tenemos las claves, mostrar el formulario没有保存配置则显示表单 form.style.display block; results.style.display none; loading.style.display none; clearBtn.style.display none; errors.textContent ; } else { //si hemos guardado claves / regiones, mostrar los resultados有保存配置则直接拉取数据 displayCarbonUsage(storedApiKey, storedRegion); results.style.display none; form.style.display none; clearBtn.style.display block; } }; function reset(e) { e.preventDefault(); //borrar almacenamiento local solo para la región只清除地区项的本地存储 localStorage.removeItem(regionName); init(); }逻辑分解如下用两个const从 LocalStorage 读取apiKey与regionName任一值为null首次使用或未保存把表单display设为block同时隐藏结果区、加载提示与清除按钮并把错误文本清空两个值都存在立即调用displayCarbonUsage(storedApiKey, storedRegion)拉取数据期间先隐藏结果区、隐藏表单、显示清除按钮reset()只删除regionName一项保留 API Key用户重新选择地区即可然后重新执行init()回到表单状态。LocalStorage 核心概念文档在此强调了一个浏览器端非常重要的概念LocalStorage是以键值对形式在浏览器中存储字符串的方式可由 JavaScript 直接读写用于管理浏览器内的数据。它的关键特性不随会话过期LocalStorage 不会自动清除与之对比SessionStorage 在浏览器关闭时会被清除。不同存储方式各有取舍需要按场景选择API 统一且兼容性好通过getItem()、setItem()、removeItem()三个方法即可完成读写删在所有现代浏览器中广泛可用按源隔离文档特别提示——浏览器扩展拥有自己独立的 LocalStorage与浏览器主窗口中打开的普通网页是不同的实例、互不干扰这提供了隔离与安全边界。你可以在开发者工具中直观验证右键页面选择检查或按 F12切到Application面板的 Local Storage 区域就能看到以键值对形式保存的apiKey、regionName即文首配图所示界面。⚠️安全提醒原文档 ✅ 思考题一般生产应用中把 API Key 放进 LocalStorage 是坏主意——因为同一来源内的任何 JS 都能读到它。本课之所以这样写仅因为该应用纯粹用于学习、不会发布到应用商店。注意一个实现细节本课讲义代码使用的键名是regionName而仓库参考答案 solution/src/index.js 中实际使用的键名是region。两者只要自洽getItem/setItem/removeItem使用同一键名即可正常工作如果你把讲义代码与 solution 混用务必统一键名否则会出现初始化读不到数据的隐蔽 bug。第 4 步处理表单提交在写displayCarbonUsage()之前先搭好首次提交的处理函数。handleSubmit接收事件参数(e)阻止默认行为我们不希望浏览器提交后刷新页面再把两个输入框的当前值传给setUpUserfunction handleSubmit(e) { e.preventDefault(); setUpUser(apiKey.value, region.value); }✅ 回顾上节课的 HTML表单有两个输入字段其value正是通过文件顶部的两个const引用捕获且两个字段都带required属性浏览器会阻止用户以空值提交天然做了一层非空校验。第 5 步setUpUser() 保存用户配置setUpUser负责把用户凭据写入 LocalStorage并为界面切换到加载中状态随后触发首次 API 调用function setUpUser(apiKey, regionName) { localStorage.setItem(apiKey, apiKey); localStorage.setItem(regionName, regionName); loading.style.display block; errors.textContent ; clearBtn.style.display block; //make initial call发起首次调用 displayCarbonUsage(apiKey, regionName); }执行顺序有讲究先落盘再改 UI最后发请求。这样即使请求失败init()重入时依然能从 LocalStorage 恢复到一致的界面状态而loading的显示让用户在等待网络响应期间有明确的反馈。第 6 步displayCarbonUsage() 调用 CO2 Signal API终于轮到核心函数。先补上文档中的 API 背景知识APIApplication Programming Interface应用程序编程接口是程序之间相互通信的标准方式——比如你要查数据库可能已有别人封装好的 API 供你调用。众多 API 类型中最流行的之一是REST APIREST 即 Representational State Transfer表现层状态转移它通过以不同方式构造 URL 来获取数据配合标准 HTTP 方法与可预测的响应格式通常是 JSON。本课使用async关键字将函数声明为异步。异步执行意味着函数发起网络请求后会交出控制权而不是让扩展界面卡死等待。由于你无法控制 API 响应快慢甚至可能完全不响应必须用异步方式处理这种不确定性——这也是try/catch必须包裹请求的原因。完整实现如下axios 在文件顶部以import axios from axios引入讲义示例中写作import axios from ../node_modules/axioswebpack 打包时两种写法均可解析但常规写法是前者参考 solution/src/index.js 第 1 行async function displayCarbonUsage(apiKey, region) { try { await axios .get(https://api.co2signal.com/v1/latest, { params: { countryCode: region, }, headers: { auth-token: apiKey, }, }) .then((response) { let CO2 Math.floor(response.data.data.carbonIntensity); //calculateColor(CO2);下一课时实现按颜色更新图标 loading.style.display none; form.style.display none; myregion.textContent region; usage.textContent Math.round(response.data.data.carbonIntensity) grams (grams C02 emitted per kilowatt hour); fossilfuel.textContent response.data.data.fossilFuelPercentage.toFixed(2) % (percentage of fossil fuels used to generate electricity); results.style.display block; }); } catch (error) { console.log(error); loading.style.display none; results.style.display none; errors.textContent Sorry, we have no data for the region you have requested.; } }逐点拆解这个大函数在做什么认证方式CO2 Signal API 使用auth-token请求头传递 API Key注意放在headers里而不是查询参数查询参数通过 axios 的params对象传入countryCode: regionaxios 会将其序列化为 URL 查询串从而按地区过滤数据数据映射响应到达后把response.data.data中的carbonIntensity碳强度单位克 CO2/千瓦时四舍五入后写入.carbon-usage把fossilFuelPercentage保留两位小数写入.fossil-fuel同时更新.my-region、隐藏 loading 与表单、显示结果容器错误路径请求失败网络错误、Key 无效、该地区无数据等任何抛错都会落入catch隐藏 loading 与结果区并在.errors中给出抱歉没有您请求地区的数据提示。对照仓库参考答案可以看到工程化上的增量solution/src/index.js 的displayCarbonUsage在渲染前增加了空值校验——if (data?.carbonIntensity null || data?.fossilFuelPercentage null) throw ...并在catch中改用console.warn记录error.message。从源码结构看这提示了实战中先校验响应结构再取字段的健壮性习惯API 可能返回 200 但载荷不完整仅靠try/catch捕获不到这类静默坏数据。构建与验证按文档要求在扩展目录执行构建并在扩展面板中刷新即可看到成果npm run build构建后到浏览器的扩展管理页刷新该扩展再点开 popup首次打开显示 API Key 与地区表单提交后看到加载中数据返回后看到地区名、克 CO2/千瓦时的碳强度与化石燃料百分比。此时唯一尚未生效的是动态图标——init()与displayCarbonUsage()中被注释掉的calculateColor/图标逻辑正是下一课时的内容。solution 中对应的完整实现co2Scale色阶 chrome.runtime.sendMessage({ action: updateIcon, ... }可参考 solution/src/index.js它印证了 popup 页面与 MV3 service worker 之间通过消息机制联动更新图标的设计。挑战题与课后练习研究挑战原文档 题选一个浏览器原生 API 深入调研例如 HTML 拖放 APIHTML Drag and Drop API、Geolocation API 等思考什么样的 API 称得上优秀文档是否清晰、错误处理如何、跨浏览器支持度如何正式作业Adopt an API。作业要求你自选一个外部 API 构建浏览器扩展硬性功能包括用于 API 参数的表单输入、带错误处理的 API 集成、用 LocalStorage 保存用户偏好、加载状态与用户反馈代码要求使用 ES6 与 async/await、try/catch错误处理并处理无网络、非法响应等边界情况验证扩展在浏览器重启后仍能工作。复习与自测本课掌握了 LocalStorage 与 API 调用这两项对职业 Web 开发者都非常有用的能力。自检时问自己这两者如何协同工作你会如何设计一个把本地存储的数据作为 API 输入的网站另外可用 5 分钟快速验证在任意网站的 DevTools Application 面板查看其 localStorage在控制台里手动localStorage.setItem/getItem一轮用 Network 面板观察表单实际提交了什么。【免费下载链接】Web-Dev-For-Beginners24 Lessons, 12 Weeks, Get Started as a Web Developer项目地址: https://gitcode.com/GitHub_Trending/we/Web-Dev-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考