Content Index API - 允许开发者向浏览器注册离线内容

Content Index API(内容索引 API)允许开发者向浏览器注册离线内容。

概念和用法

就目前情况而言,离线网络内容不容易被用户发现。内容索引允许开发者告诉浏览器它们特定的离线内容。这允许用户发现和查看可用的内容,同时让开发者有能力添加和管理这些内容。例如,一个新闻网站在后台预取最新的文章,或者一个内容流应用注册下载的内容。

内容索引 API 是对服务工作线程的扩展,它允许开发者在当前服务工作线程的范围内,添加已经缓存的页面的 URL 和元数据。然后,浏览器可以使用这些条目来向用户显示离线阅读。作为一个开发者,你也可以在你的应用程序中显示这些条目。

被索引的条目不会自动过期。最好提供一个清除条目或定期删除较旧条目的接口。

该 API 支持与 HTML 文档相对应的索引 URL。例如,无法直接为缓存的媒体文件的 URL 建立索引。相反,你需要提供一个显示媒体的页面的 URL,并且该页面可以离线工作。

接口

ContentIndex

ContentIndex 接口提供了功能以注册可离线使用的内容。

ContentIndexEvent

Content Index APIContentIndexEvent 接口定义了用于表示 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 初始定义。

桌面浏览器兼容性

特性ChromeEdgeFirefoxInternet ExplorerOperaSafari
基础支持 不支持84 不支持 不支持 不支持 不支持
add 不支持84 不支持 不支持 不支持 不支持
delete 不支持84 不支持 不支持 不支持 不支持
getAll 不支持84 不支持 不支持 不支持 不支持

移动浏览器兼容性

特性AndroidChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
基础支持8484 未知 不支持 未知 不支持 不支持
add8484 未知 不支持 未知 不支持 不支持
delete8484 未知 不支持 未知 不支持 不支持
getAll8484 未知 不支持 未知 不支持 不支持

相关链接