You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/zh/5-browser-extension/2-forms-browsers-local-storage/README.md

11 KiB

浏览器扩展项目第二部分:调用 API使用本地存储

课前测验

课前测验

介绍

在本课中,你将通过提交浏览器扩展的表单来调用 API并在浏览器扩展中显示结果。此外你还将学习如何将数据存储在浏览器的本地存储中以供将来参考和使用。

按照相关文件中的编号段落,了解代码应该放置的位置。

设置扩展中需要操作的元素:

到目前为止,你已经为浏览器扩展构建了表单和结果 <div> 的 HTML。从现在开始你需要在 /src/index.js 文件中工作,并逐步构建你的扩展。参考上一课了解项目设置和构建过程。

index.js 文件中工作,首先创建一些 const 变量来保存与各个字段相关的值:

// 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');

所有这些字段都是通过它们的 CSS 类引用的,这是你在上一课的 HTML 中设置的。

添加监听器

接下来,为表单和重置按钮添加事件监听器,这样当用户提交表单或点击重置按钮时,会触发相应的操作,并在文件底部添加初始化应用的调用:

form.addEventListener('submit', (e) => handleSubmit(e));
clearBtn.addEventListener('click', (e) => reset(e));
init();

注意这里使用了简写方式来监听提交或点击事件,以及事件如何传递给 handleSubmitreset 函数。你能写出这种简写的等效长格式吗?你更喜欢哪种方式?

构建 init()reset() 函数:

现在你将构建初始化扩展的函数 init()

function init() {
	//if anything is in localStorage, pick it up
	const storedApiKey = localStorage.getItem('apiKey');
	const storedRegion = localStorage.getItem('regionName');

	//set icon to be generic green
	//todo

	if (storedApiKey === null || storedRegion === null) {
		//if we don't have the keys, show the form
		form.style.display = 'block';
		results.style.display = 'none';
		loading.style.display = 'none';
		clearBtn.style.display = 'none';
		errors.textContent = '';
	} else {
        //if we have saved keys/regions in localStorage, show results when they load
        displayCarbonUsage(storedApiKey, storedRegion);
		results.style.display = 'none';
		form.style.display = 'none';
		clearBtn.style.display = 'block';
	}
};

function reset(e) {
	e.preventDefault();
	//clear local storage for region only
	localStorage.removeItem('regionName');
	init();
}

在这个函数中,有一些有趣的逻辑。阅读代码后,你能看出发生了什么吗?

  • 设置两个 const 来检查用户是否在本地存储中保存了 APIKey 和区域代码。
  • 如果其中任何一个为 null通过将表单样式设置为 'block' 来显示表单。
  • 隐藏结果、加载状态和清除按钮,并将任何错误文本设置为空字符串。
  • 如果存在 key 和 region则启动以下流程
    • 调用 API 获取碳使用数据。
    • 隐藏结果区域。
    • 隐藏表单。
    • 显示重置按钮。

在继续之前,了解浏览器中一个非常重要的概念是很有用的:LocalStorage。LocalStorage 是一种在浏览器中以 key-value 对形式存储字符串的有用方式。这种类型的 Web 存储可以通过 JavaScript 操作来管理浏览器中的数据。LocalStorage 不会过期,而另一种 Web 存储 SessionStorage 会在浏览器关闭时清除。这些存储类型在使用上各有优缺点。

注意 - 你的浏览器扩展有自己的本地存储;主浏览器窗口是一个不同的实例,行为独立。

你可以将 APIKey 设置为一个字符串值,例如,你可以通过“检查”网页(右键单击浏览器并选择检查)并转到应用程序选项卡查看存储内容来在 Edge 上看到它。

本地存储面板

思考哪些情况下你不应该将某些数据存储在 LocalStorage 中。通常,将 APIKey 放在 LocalStorage 中是一个糟糕的主意!你能看出原因吗?在我们的案例中,由于我们的应用仅用于学习且不会部署到应用商店,我们将使用这种方法。

注意,你使用 Web API 操作 LocalStorage可以通过 getItem()setItem()removeItem()。它在各个浏览器中都得到了广泛支持。

在构建 displayCarbonUsage() 函数(在 init() 中调用)之前,让我们先构建处理初始表单提交的功能。

处理表单提交

创建一个名为 handleSubmit 的函数,该函数接受一个事件参数 (e)。阻止事件传播(在这种情况下,我们希望阻止浏览器刷新),并调用一个新函数 setUpUser,传入 apiKey.valueregion.value 作为参数。通过这种方式,你可以使用通过初始表单填充的字段中获取的两个值。

function handleSubmit(e) {
	e.preventDefault();
	setUpUser(apiKey.value, region.value);
}

回顾一下 - 你在上一课中设置的 HTML 有两个输入字段,其 values 是通过你在文件顶部设置的 const 捕获的,并且它们都是 required,因此浏览器会阻止用户输入空值。

设置用户

接下来是 setUpUser 函数,这里你将为 apiKey 和 regionName 设置本地存储值。添加一个新函数:

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);
}

这个函数会在调用 API 时显示加载消息。到此为止,你已经到达了创建这个浏览器扩展最重要的函数!

显示碳使用数据

最后,是时候查询 API 了!

在进一步操作之前,我们应该讨论一下 API。API应用程序编程接口,是 Web 开发人员工具箱中的关键元素。它们为程序之间的交互和接口提供了标准方式。例如,如果你正在构建一个需要查询数据库的网站,可能有人已经为你创建了一个 API 可以使用。虽然 API 有很多种类型,其中一种最流行的是 REST API

“REST” 的全称是“表述性状态转移”,它通过各种配置的 URL 来获取数据。研究一下开发人员可用的各种 API 类型。哪种格式对你更有吸引力?

关于这个函数,有一些重要的事情需要注意。首先,注意 async 关键字。将函数写成异步运行意味着它会等待某个操作(例如数据返回)完成后再继续。

这里有一个关于 async 的简短视频:

管理 Promise 的 Async 和 Await

🎥 点击上方图片观看关于 async/await 的视频。

创建一个新函数来查询 C02Signal API

import axios from '../node_modules/axios';

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.';
	}
}

这是一个较大的函数。这里发生了什么?

  • 遵循最佳实践,你使用了 async 关键字使这个函数异步运行。函数包含一个 try/catch 块,因为当 API 返回数据时它会返回一个 Promise。由于你无法控制 API 响应的速度(它可能根本不响应!),你需要通过异步调用来处理这种不确定性。
  • 你正在查询 co2signal API 以获取区域数据,使用你的 APIKey。要使用该 key你需要在请求头参数中使用一种身份验证方式。
  • 一旦 API 响应,你将其响应数据的各个元素分配给屏幕上设置的显示数据的部分。
  • 如果出现错误或没有结果,你会显示错误消息。

使用异步编程模式是工具箱中另一个非常有用的工具。阅读各种配置方式了解这种代码类型。

恭喜你!如果你构建了扩展(npm run build)并在扩展面板中刷新它,你就有了一个可用的扩展!唯一没有工作的部分是图标,你将在下一课中修复它。


🚀 挑战

我们在这些课程中讨论了几种类型的 API。选择一个 Web API深入研究它提供的功能。例如查看浏览器中可用的 APIHTML 拖放 API。在你看来,什么样的 API 是优秀的?

课后测验

课后测验

复习与自学

在本课中你学习了 LocalStorage 和 API它们对专业的 Web 开发人员来说都非常有用。你能想到这两者如何协同工作吗?思考一下如何设计一个网站来存储供 API 使用的项目。

作业

选择一个 API


免责声明
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保准确性,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言的文档作为权威来源。对于关键信息,建议使用专业人工翻译。对于因使用本翻译而引起的任何误解或误读,我们概不负责。