从您的 PWA 触发安装

警告:此处描述的技术依赖于 beforeinstallprompt 事件,该事件是非标准的,目前仅在基于 Chromium 的浏览器中实现。

默认情况下,如果用户访问您的网站,并且浏览器确定该网站是 可以作为 PWA 安装,那么浏览器将显示一些内置的 UI——例如 URL 栏中的图标——来安装该网站。如果用户点击图标,则浏览器将显示一个安装提示,其中至少包含应用的 名称图标。如果用户同意安装应用,则将安装该应用。

但是,您可以实现自己的应用内 UI 来询问用户是否要安装应用,这将触发安装提示。这样做的好处是

  • 您可以提供有关应用的更多上下文,向用户解释为什么他们可能希望将应用安装为 PWA。
  • 与浏览器的默认 UI 相比,应用内安装 UI 更有可能更容易被用户发现和理解。

添加应用内安装 UI

首先,在应用中添加一些 UI,指示用户可以安装它。例如

html
<button id="install" hidden>Install</button>

我们正在设置按钮的 hidden 属性,因为如果用户使用无法安装它的浏览器访问应用,我们不希望安装 UI 可见。接下来,我们将了解如何仅在支持本地安装 PWA 的浏览器上使按钮可见。

侦听 beforeinstallprompt

一旦浏览器确定它可以安装应用,它就会在全局 Window 范围内触发 beforeinstallprompt 事件。

在我们的主应用代码中,我们将侦听此事件

js
// main.js

let installPrompt = null;
const installButton = document.querySelector("#install");

window.addEventListener("beforeinstallprompt", (event) => {
  event.preventDefault();
  installPrompt = event;
  installButton.removeAttribute("hidden");
});

此处的事件处理程序执行三件事

  • 对事件调用 preventDefault()。这将阻止浏览器显示它自己的安装 UI。
  • 获取传递到处理程序的事件对象的引用。这是一个 BeforeInstallPromptEvent 实例,它将使我们能够提示用户安装应用。
  • 通过从按钮中删除 hidden 属性来显示我们的应用内安装 UI。

触发安装提示

接下来,我们需要为我们的应用内安装按钮添加一个点击处理程序

js
// main.js

installButton.addEventListener("click", async () => {
  if (!installPrompt) {
    return;
  }
  const result = await installPrompt.prompt();
  console.log(`Install prompt was: ${result.outcome}`);
  disableInAppInstallPrompt();
});

function disableInAppInstallPrompt() {
  installPrompt = null;
  installButton.setAttribute("hidden", "");
}

installPrompt 变量在我们的 beforeinstallprompt 事件处理程序中使用 BeforeInstallPromptEvent 对象初始化。如果 installPrompt 由于任何原因尚未初始化,我们将不做任何操作。

否则,我们将调用其 prompt() 方法。这将显示安装提示,并返回一个 Promise,该提示将解析为一个对象,指示应用是否已安装。特别是,其 outcome 属性如果用户选择安装应用,则为 "accepted",如果用户驳回提示,则为 "dismissed"

无论哪种方式,我们都必须在调用 prompt() 后重置我们的状态,因为我们只能对每个 BeforeInstallPromptEvent 实例调用一次。因此,我们重置 installPrompt 变量并再次隐藏安装按钮。

响应应用安装

根据浏览器和平台的不同,浏览器可能仍然会提供它自己的 UI 来安装应用。这意味着应用仍然可以安装,而无需经过我们的应用内安装 UI。如果发生这种情况,我们希望禁用应用内安装 UI,否则我们将在已安装的应用中显示它。

为此,我们可以侦听 appinstalled 事件,该事件在应用已安装时在全局 Window 范围内触发

js
// main.js

window.addEventListener("appinstalled", () => {
  disableInAppInstallPrompt();
});

function disableInAppInstallPrompt() {
  installPrompt = null;
  installButton.setAttribute("hidden", "");
}

响应特定平台的应用安装

上述示例没有涵盖的一种情况是,您有一个特定平台的应用版本,以及一个 Web 应用,并且您希望根据特定平台的应用是否已安装来个性化 Web 应用体验。如果您已经安装了特定平台的应用,您可能不想邀请用户安装 PWA,或者您可能希望邀请他们前往特定平台的应用以查看内容。

这可以使用 Navigator.getInstalledRelatedApps() 方法来处理,该方法允许您检测已安装的相关特定平台应用(或 PWA)并做出适当的响应。

例如

js
const relatedApps = await navigator.getInstalledRelatedApps();

// Search for a specific installed platform-specific app
const psApp = relatedApps.find((app) => app.id === "com.example.myapp");

if (psApp) {
  // Update UI as appropriate
}

此方法还可以与 beforeinstallprompt 结合使用,以根据特定平台应用的可用性抑制浏览器的安装 UI

js
window.addEventListener("beforeinstallprompt", async (event) => {
  const relatedApps = await navigator.getInstalledRelatedApps();

  // Search for a specific installed platform-specific app
  const psApp = relatedApps.find((app) => app.id === "com.example.myapp");

  if (psApp) {
    event.preventDefault();
    // Update UI as appropriate
  }
});

另请参阅