# 让它可安装

> 超越最低门槛：满足每一条可安装标准，并设计赢得「添加到主屏幕」的安装时机。

完成本指南后，应用会通过 Chrome 的安装标准，只在能响应的浏览器上显示自己的安装按钮，给 iOS 用户提供分享面板路径而不是一个无效按钮，并能在运行时知道自己是否以已安装状态运行。请从一个已经满足[入门](/zh/guides/getting-started/)门槛的站点开始，本指南在其上构建安装体验。

## 满足 Chrome 的全部标准，包括互动条件

web.dev 的 install-criteria 文章列出了 Chrome 触发 `beforeinstallprompt` 前的检查：应用尚未安装；用户至少点击或轻触过页面一次，并在页面停留至少 30 秒（任何时候都算，包括此前的访问）；页面通过 HTTPS 提供；manifest 含 `name` 或 `short_name`、192 px 与 512 px 的 `icons`、`start_url`、取值为 `fullscreen`、`standalone`、`minimal-ui` 或 `window-controls-overlay` 的 `display`，且没有 `prefer_related_applications: true`。互动条件最常被误认为 bug：在全新的浏览器配置文件里，头半分钟内事件不会触发。把 `scope` 设成覆盖应用拥有的每条路由；`scope` 之外的 URL 打开时会带上浏览器界面。

## 捕获提示并显示自己的按钮

在 Chromium 浏览器（Chrome、Edge、Samsung Internet）中，一旦满足标准，浏览器就会触发 `beforeinstallprompt`。调用 `preventDefault()` 抑制移动端浏览器自带的横幅，保留事件并显示按钮。`prompt()` 解析出的 `outcome` 为 `"accepted"` 或 `"dismissed"`（MDN，`BeforeInstallPromptEvent.userChoice`），而被延迟的事件只能 prompt 一次：

```js
let deferredPrompt = null;
const installButton = document.querySelector('#install');

window.addEventListener('beforeinstallprompt', (event) => {
  event.preventDefault();
  deferredPrompt = event;
  installButton.hidden = false;
});

installButton.addEventListener('click', async () => {
  if (!deferredPrompt) return;
  const { outcome } = await deferredPrompt.prompt();
  deferredPrompt = null;
  installButton.hidden = true;
  if (outcome === 'dismissed') {
    localStorage.setItem('install-dismissed-at', String(Date.now()));
  }
});

window.addEventListener('appinstalled', () => {
  installButton.hidden = true;
  deferredPrompt = null;
});
```

按钮初始隐藏，在从不触发该事件的 Firefox 与 Safari 上保持隐藏（MDN 将该事件列为非 Baseline）。当用户通过浏览器菜单而非你的按钮安装时，`appinstalled` 监听器同样会隐藏按钮。在用户做出表明意图的动作之后再显示按钮，例如保存第二条记录；首屏即弹出的提示是在应用展示任何价值之前就索要承诺，而记录拒绝时间戳可以让你等一周再问。

## 给 iOS 用户分享面板的说明

iOS 与 iPadOS 上的 Safari 没有 `beforeinstallprompt`，路径是 Share 按钮，然后 **Add to Home Screen**（英文界面），WebKit 的 Web Push 公告如此描述。MDN 指出自 iOS 16.4 起，iOS 上的 Chrome、Edge、Firefox 与 Orion 的分享菜单也有同一入口。检测平台与 standalone 状态，然后显示说明而不是按钮：

```js
const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent) && !window.MSStream;
const isStandalone =
  window.matchMedia('(display-mode: standalone)').matches || navigator.standalone === true;

if (isIos && !isStandalone) {
  document.querySelector('#ios-install-hint').hidden = false; // 「点 Share，再点 Add to Home Screen」
}
```

`navigator.standalone` 是 Safari 独有、表示主屏幕 Web 应用的属性；`display-mode` 媒体查询是跨浏览器的检测，也是 web.dev customize-install 文章中 `getPWADisplayMode()` 辅助函数所用的方法。

## 逐条路径验证

桌面版 Chrome 在满足标准的页面上会在地址栏右侧显示安装图标；菜单路径是 **More** > **Cast, save, and share** > **Install page as app…**（英文界面，Chrome 帮助）。Android 上的路径是 **More** > **Install and create shortcut** > **Install**。安装后启动应用，在控制台确认 `matchMedia('(display-mode: standalone)').matches` 为 `true`，且安装按钮已隐藏。要从干净状态重测，在已安装窗口里走 **More** > **Uninstall [app name]** > **Remove** 卸载。

:::observed
Chrome 帮助页 "Use web apps"（英文界面，2026-10-03 读取）给 Android 菜单项的名称是 **Install and create shortcut**，而不是 "Install app" 或 "Add to Home screen"。提示 Android 用户去找 "Add to Home screen" 会把他们引向 Chrome 已不再显示的标签；请引用当前标签，或直接指向地址栏中的安装图标。
:::

## 另请参阅

- [入门](/zh/guides/getting-started/)
- [安装提示](/zh/reference/installation/install-prompt/)
- [iOS 添加到主屏幕](/zh/reference/installation/ios-add-to-home-screen/)
- [安装提示兼容性](/zh/compatibility/install-prompt/)
- [How to provide your own in-app install experience](https://web.dev/articles/customize-install)（web.dev）
- [Installation criteria](https://web.dev/articles/install-criteria)（web.dev）

← 返回[指南](/zh/guides/)总览。