跳转到内容

让它可安装

发布于

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

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

Section titled “满足 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 一次:

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 与 iPadOS 上的 Safari 没有 beforeinstallprompt,路径是 Share 按钮,然后 Add to Home Screen(英文界面),WebKit 的 Web Push 公告如此描述。MDN 指出自 iOS 16.4 起,iOS 上的 Chrome、Edge、Firefox 与 Orion 的分享菜单也有同一入口。检测平台与 standalone 状态,然后显示说明而不是按钮:

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 卸载。

← 返回指南总览。