Content Index API - 允许开发者向浏览器注册离线内容
Content Index API(内容索引 API)允许开发者向浏览器注册离线内容。
概念和用法
就目前情况而言,离线网络内容不容易被用户发现。内容索引允许开发者告诉浏览器它们特定的离线内容。这允许用户发现和查看可用的内容,同时让开发者有能力添加和管理这些内容。例如,一个新闻网站在后台预取最新的文章,或者一个内容流应用注册下载的内容。
内容索引 API 是对服务工作线程的扩展,它允许开发者在当前服务工作线程的范围内,添加已经缓存的页面的 URL 和元数据。然后,浏览器可以使用这些条目来向用户显示离线阅读。作为一个开发者,你也可以在你的应用程序中显示这些条目。
被索引的条目不会自动过期。最好提供一个清除条目或定期删除较旧条目的接口。
该 API 支持与 HTML 文档相对应的索引 URL。例如,无法直接为缓存的媒体文件的 URL 建立索引。相反,你需要提供一个显示媒体的页面的 URL,并且该页面可以离线工作。
接口
ContentIndex
ContentIndex 接口提供了功能以注册可离线使用的内容。
ContentIndexEvent
Content Index API 的 ContentIndexEvent 接口定义了用于表示 contentdelete 事件的对象。
服务工作线程扩展
在内容索引 API 规范中指定了 ServiceWorker 的以下新增内容,以提供使用内容索引的入口点。
ServiceWorkerRegistration.index 只读
返回对 ContentIndex 接口的引用,以对缓存的页面建立索引。
ServiceWorkerGlobalScope.oncontentdelete
每当触发 contentdelete 事件时,都会触发该事件处理程序。当用户代理删除内容时,会触发该事件。
实例
以下所有实例均假定服务工作线程已注册。有关更多信息,请参见 Service Worker API。
功能检测和接口访问
在这里,我们获得对 ServiceWorkerRegistration 的引用,然后检查 index 属性,该属性使我们可以访问内容索引接口。
// 获取注册引用
const registration = await navigator.serviceWorker.ready;
// 功能检测
if ('index' in registration) {
// 内容索引 API 功能
const contentIndex = registration.index;
}
添加到内容索引
在这里,我们以正确的格式声明一个项目,并创建一个异步函数,该异步函数使用 add() 方法将其注册到内容索引中。
// 我们的内容
const item = {
id: 'post-1',
url: '/posts/amet.html',
title: 'Amet consectetur adipisicing',
description: 'Repellat et quia iste possimus ducimus aliquid a aut eaque nostrum.',
icons: [{
src: '/media/dark.png',
sizes: '128x128',
type: 'image/png',
}],
category: 'article'
};
// 我们的异步函数来添加索引内容
async function registerContent(data) {
const registration = await navigator.serviceWorker.ready;
// 检测内容索引是否可用
if (!registration.index) {
return;
}
// 注册内容
try {
await registration.index.add(data);
} catch (e) {
console.log('无法注册内容:', e.message);
}
}
检索当前索引中的项目
以下实例显示了一个异步函数,该函数检索内容索引中的项目,并遍历每个条目,为接口建立一个列表。
async function createReadingList() {
// 访问我们的服务工作线程
const registration = await navigator.serviceWorker.ready;
// 获取我们的索引条目
const entries = await registration.index.getAll();
// 创建一个父元素
const readingListElem = document.createElement('div');
if (!entries.length) {
// 如果没有条目,则显示一条消息
const message = document.createElement('p');
message.innerText = '您目前没有保存任何文章以供离线阅读。'
readingListElem.append(message);
} else {
// 如果存在条目,则在内容链接的列表中显示
const listElem = document.createElement('ul');
for (const entry of entries) {
const listItem = document.createElement('li');
const anchorElem = document.createElement('a');
anchorElem.innerText = entry.title;
anchorElem.setAttribute('href', entry.url);
listElem.append(listItem);
}
readingListElem.append(listElem);
}
}
注销索引内容
以下是一个异步函数,该函数从内容索引中删除一项。
async function unregisterContent(article) {
// 获取注册引用
const registration = await navigator.serviceWorker.ready;
// 检测内容索引是否可用
if (!registration.index)
return;
// 从索引中注销内容
await registration.index.delete(article.id);
}
以上所有方法均在 服务工作线程 范围内可用。可通过 WorkerGlobalScope.self 属性访问它们:
// 服务工作线程脚本
self.registration.index.add(item);
self.registration.index.delete(item.id);
const contentIndexItems = self.registration.index.getAll();
contentdelete 事件
当从用户代理界面中删除某项时,服务工作线程会收到一个 contentdelete 事件。
self.addEventListener('contentdelete', (event) => {
console.log(event.id);
// 记录内容索引 ID,然后可用来确定要从缓存中删除哪些内容
});
contentdelete 事件只有在由于与浏览器内置用户界面的交互而发生删除时才触发。调用 ContentIndex.delete 方法时不会触发。
规范
| 规范 | 状态 | 备注 |
|---|---|---|
| Unknown | Unknown | 初始定义。 |
桌面浏览器兼容性
| 特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari |
|---|---|---|---|---|---|---|
| 基础支持 | 不支持 | 84 | 不支持 | 不支持 | 不支持 | 不支持 |
add | 不支持 | 84 | 不支持 | 不支持 | 不支持 | 不支持 |
delete | 不支持 | 84 | 不支持 | 不支持 | 不支持 | 不支持 |
getAll | 不支持 | 84 | 不支持 | 不支持 | 不支持 | 不支持 |
移动浏览器兼容性
| 特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari |
|---|---|---|---|---|---|---|---|
| 基础支持 | 84 | 84 | 未知 | 不支持 | 未知 | 不支持 | 不支持 |
add | 84 | 84 | 未知 | 不支持 | 未知 | 不支持 | 不支持 |
delete | 84 | 84 | 未知 | 不支持 | 未知 | 不支持 | 不支持 |
getAll | 84 | 84 | 未知 | 不支持 | 未知 | 不支持 | 不支持 |