Web 应用具有广泛的影响力。它们可在多个平台上运行。它们易于通过链接共享。但传统上,它们缺乏与操作系统的集成。不久前,它们甚至无法安装。幸运的是,这种情况已经改变,现在我们可以利用这种集成来为我们的 PWA 添加有用的功能。让我们探索其中的一些选项。
使用文件系统
使用文件的典型用户工作流程如下所示
- 从设备中选择文件或文件夹并直接打开。
- 对这些文件或文件夹进行更改,然后将更改直接保存回去。
- 创建新的文件和文件夹。
在 File System Access API 之前,Web 应用无法做到这一点。打开文件需要文件上传,保存更改需要用户下载它们,并且 Web 完全无法在用户的文件系统中创建新的文件和文件夹。
打开文件
要打开文件,我们使用 window.showOpenFilePicker()
方法。请注意,此方法需要用户手势,例如按钮点击。以下是打开文件的其余设置
- 从文件系统访问的文件选择器 API 中捕获 文件句柄。这为您提供有关文件的基本信息。
- 使用句柄的
getFile()
方法,您将获得一种特殊的Blob
,称为File
,其中包含有关文件的其他只读属性(例如名称和上次修改日期)。因为它是一个 Blob,所以可以在其上调用 Blob 方法,例如text()
,以获取其内容。
// Have the user select a file.
const [ handle ] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await handle.getFile();
// Get the file content.
// Also available, slice(), stream(), arrayBuffer()
const content = await file.text();
保存更改
要保存对文件的更改,您也需要用户手势;然后
- 使用文件句柄创建
FileSystemWritableFileStream
。 - 对流进行更改。这不会就地更新文件;相反,通常会创建一个临时文件。
- 最后,当您完成更改后,您关闭流,这将把更改从临时文件移动到永久文件。
让我们在代码中看看
// Make a writable stream from the handle.
const writable = await handle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
文件处理
File System Access API 允许您从应用内打开文件,但反过来呢?用户希望将他们喜欢的应用设置为打开文件的默认应用。File Handling API 是一个实验性 API,它允许已安装的 PWA:在用户设备上注册为文件处理程序,在您的 Web 应用清单中指定您的 PWA 支持的 MIME 类型和文件扩展名。您可以为您的支持的扩展名指定自定义文件图标。
注册后,您安装的 PWA 将在用户的文件系统中显示为一个选项,允许他们直接在其中打开文件。以下是 PWA 读取文本文件的清单设置示例
...
"file_handlers": [
{
"action": "/open-file",
"accept": {
"text/*": [".txt"]
}
}
]
...
URL 处理
通过 URL 处理,您的 PWA 可以从操作系统捕获属于其作用域的链接,并在 PWA 窗口中呈现它们,而不是默认浏览器的选项卡。例如,如果您收到指向 PWA 的消息,或者单击 PWA 中的深层链接(指向特定内容片段的 URL),则内容将在独立窗口中打开。
当使用 WebAPK 时,例如当用户使用 Chrome 安装 PWA 时,此行为在 Android 上自动可用。无法在从 Safari 安装在 iOS 和 iPadOS 上的 PWA 上捕获 URL。
对于桌面浏览器,Web 浏览器社区创建了一个新的规范。此规范目前是 实验性的;它添加了一个新的清单文件成员:url_handlers
。此属性需要 PWA 想要捕获的来源数组。您的 PWA 的来源将自动获得授权,而每个其他来源都必须通过名为 web-app-origin-association
的文件接受该操作处理。例如,如果您的 PWA 的清单托管在 web.dev 上,并且您想添加 app.web.dev 来源,它将如下所示
"url_handlers": [
{"origin": "https://app.web.dev"},
]
在这种情况下,浏览器将检查 app.web.dev/.well-known/web-app-origin-association
中是否存在文件,接受来自 PWA 作用域 URL 的 URL 处理。开发人员必须创建此文件。在以下示例中,该文件如下所示
{
"web_apps": [
{
"manifest": "/mypwa/app.webmanifest",
"details": {
"paths": [ "/*" ]
}
}
]
}
URL 协议处理
URL 处理适用于标准 https
协议 URL,但可以使用自定义 URI 方案,例如 pwa://
。在某些操作系统中,已安装的应用通过注册其方案来获得此能力。
对于 PWA,此功能通过 URL 协议处理程序 API 启用,该 API 仅在桌面设备上可用。您只能通过在应用商店中分发 PWA 来允许移动设备的自定义协议。
要注册,您可以使用 registerProtocolHandler() 方法,或在您的清单中使用 protocol_handlers
成员,其中包含所需的方案和您想要在 PWA 上下文中加载的 URL,例如
...
{
"protocol_handlers": [
{
"protocol": "web+pwa",
"url": "/from-protocol?value=%s"
},
]
}
...
您可以将 URL from-protocol
路由到正确的处理程序,并在您的 PWA 中获取查询字符串 value
。%s
是触发操作的转义 URL 的占位符,因此如果您在某处有一个链接,例如 <a href="web+pwa://testing">
,您的 PWA 将打开 /from-protocol?value=testing
。
调用其他应用
您可以使用 URI 方案连接到用户设备上每个平台上的任何其他已安装应用(PWA 或非 PWA)。您只需要创建一个链接或使用 navigator.href
并指向您想要的 URI 方案,以 URL 转义形式传递参数即可。
您可以使用众所周知的标准方案,例如 tel:
用于电话呼叫,mailto:
用于发送电子邮件,或 sms:
用于短信;或者您可以了解其他应用的 URL 方案,例如来自知名的消息传递、地图、导航、在线会议、社交网络和应用商店。
Web Share
借助 Web Share API,您的 PWA 可以通过共享渠道将内容发送到设备上的其他已安装应用。
该 API 仅在具有 share
机制的操作系统上可用,包括 Android、iOS、iPadOS、Windows 和 ChromeOS。您可以共享包含以下内容的对象
- 文本(
title
和text
属性) - URL(
url
属性) - 文件(
files
属性)。
要检查当前设备是否可以共享,对于简单数据(如文本),您可以检查是否存在 navigator.share()
方法;要共享文件,您可以检查是否存在 navigator.canShare()
方法。
您可以通过调用 navigator.share(objectToShare)
来请求共享操作。该调用返回一个 Promise,该 Promise 解析为 undefined
或拒绝并抛出异常。
Web Share Target
Web Share Target API 允许您的 PWA 成为来自该设备上另一个应用的共享操作的目标,无论它是 PWA 还是非 PWA。您的 PWA 接收由另一个应用共享的数据。
它目前在带有 WebAPK 和 ChromeOS 的 Android 上可用,并且仅在用户安装您的 PWA 后才有效。浏览器在安装应用时在操作系统内注册共享目标。
您可以在清单中使用在 Web Share Target 草案规范 中定义的 share_target
成员来设置 Web 共享目标。share_target
设置为具有某些属性的对象
action
- 将在 PWA 窗口中加载的 URL,该窗口应接收共享数据。
method
- 将用于操作的 HTTP 谓词方法,例如
GET
、POST
或PUT
。 enctype
- (可选)参数的编码类型,默认值为
application/x-www-form-urlencoded
,但对于POST
等方法,也可以设置为multipart/form-data
。 params
- 一个对象,它将共享数据(来自键:
title
、text
、url
和files
,来自 Web Share)映射到浏览器将在 URL 中(在method: 'GET'
上)或在使用选定编码的请求正文中传递的参数。
例如,您可以为您的 PWA 定义您想要接收共享数据(仅标题和 URL),方法是在您的清单中添加
...
"share_target": {
"action": "/receive-share/",
"method": "GET",
"params": {
"title": "shared_title",
"url": "shared_url"
}
}
...
从之前的示例中,如果系统中的任何应用正在共享带有标题的 URL,并且用户从对话框中选择了您的 PWA,则浏览器将创建一个新的导航到您的来源的 /receive-share/?shared_title=AAA&shared_url=BBB
,其中 AAA 是共享标题,BBB 是共享 URL。您可以使用 JavaScript 通过使用 URL
构造函数 解析 window.location
字符串来读取该数据。
浏览器将使用您清单中的 PWA 名称和图标来填充操作系统的共享条目。您不能为此目的选择不同的集合。
有关更详细的示例以及如何接收文件,请查看 使用 Web Share Target API 接收共享数据
联系人选择器
借助 Contact Picker API,您可以请求设备呈现一个原生对话框,其中包含用户的所有联系人,以便用户可以选择一个或多个。然后,您的 PWA 可以从这些联系人处接收您想要的数据。
Contact Picker API 主要在移动设备上可用,并且所有操作都通过兼容平台上的 navigator.contacts
接口完成。
您可以请求使用 navigator.contacts.getProperties()
查询可用的属性,并使用所需属性的列表请求单个或多个联系人选择。
一些示例属性包括 name
、email
、address
和 tel
。当您要求用户选择一个或多个联系人时,您可以调用 navigator.contacts.select(properties)
,并传递您想要在返回中获取的属性数组。
以下示例将列出选择器接收到的联系人。
async function getContacts() {
const properties = ['name', 'email', 'tel'];
const options = { multiple: true };
try {
const contacts = await navigator.contacts.select(properties, options);
console.log(contacts);
} catch (ex) {
// Handle any errors here.
}
}