安装中的概念
安装横幅与 beforeinstallprompt
发布于 更新于
beforeinstallprompt 事件给 Chromium 页面一个只能使用一次的对象,应用自己的横幅或按钮可以借它打开浏览器安装提示。页面可以延后提示,但在收到事件、确认这条安装路径可用之前,应让自己的安装控件保持隐藏。
BCD api.BeforeInstallPromptEvent 把 Chrome 标为从 44 支持,把 Samsung Internet Android 标为从 5.0 支持;Edge 记录为 "mirror"。兼容性数据列出目标浏览器。BCD 未记录 Firefox 或 Safari 支持;其 api.BeforeInstallPromptEvent.prompt 条目把 Chrome 44 至 75 记录为部分实现,Promise 兑现时没有返回值,Chrome 76 起才记录结果对象。这个事件尚未标准化,在 Firefox 和 Safari 中不存在,因此安装横幅必须有明确的无事件路径。
工作原理
链接到“工作原理”一节在 window 上监听事件,调用 preventDefault(),保存事件对象,然后显示安装控件。在安装控件的点击处理器中调用 prompt()。MDN 指出,prompt() 必须在用户动作的处理器中调用,并且每个 BeforeInstallPromptEvent 只能调用一次。提示流程结束后应清除已保存的事件。代码需要覆盖 Chrome 44 至 75 时,应从 userChoice 读取结果,因为这些版本的 prompt() 不返回结果对象。
| 状态 | 横幅动作 | 页面获得的依据 |
|---|---|---|
| 事件尚未触发 | 隐藏程序化安装按钮 | 页面没有可用的提示对象 |
beforeinstallprompt 触发 |
保存事件并显示按钮 | 浏览器判定应用可使用这条安装流程 |
prompt() 结束 |
隐藏按钮并丢弃事件 | userChoice 提供 "accepted" 或 "dismissed";Chrome 76 起 prompt() 本身才返回该结果对象 |
appinstalled 触发 |
隐藏安装推广并清除状态 | 浏览器报告应用已安装 |
| 没有事件 API | 不调用 prompt(),改为显示浏览器对应的帮助 |
BCD 未记录 Firefox 或 Safari 支持 BeforeInstallPromptEvent |
preventDefault() 控制支持浏览器中该事件的默认安装推广。Chrome 的 mini-infobar 更新说明,从 Chrome 76 起,这个调用可阻止 mini-infobar。页面横幅本身不会安装应用;它只是向用户提供控件,稍后由控件调用浏览器拥有的 prompt() 方法。
MDN 将 outcome 为 "accepted" 定义为用户安装了应用。还应监听 appinstalled,这样从保存事件之外的浏览器 UI 完成安装时也能撤下推广。MDN 安装指南也要求调用 prompt() 后清除已保存的事件,因为同一个事件不能再次使用。
应把事件对象和横幅当成同一份状态。导航会丢弃 JavaScript 对象,新的文档要等待自己的事件;用户拒绝提示后,这个对象也不再有用。MDN 的事件示例在 prompt() 返回后隐藏按钮并清除引用,appinstalled 示例则在用户从其他浏览器入口完成安装时做同样的清理。这样,页面不会留下仍然可见、却指向已经消耗或不存在事件的控件。
最终确认仍由浏览器负责。页面可以决定何时显示自己的推广,以及何时调用 prompt();在已记录的 Chrome 支持范围内,userChoice 会报告用户在浏览器 UI 中作出的选择。应用分析应读取该结果,不应使用页面自己的成功状态替代浏览器确认。当结果为 "dismissed" 时,撤下与本次事件对应的横幅,等待以后新的 beforeinstallprompt 事件重新建立状态。
BCD 对 Firefox 和 Safari 记录的是 version_added: false。特性检测可以选择说明文字,却不能生成浏览器安装提示。回退说明应保持简短,同时保留浏览器菜单或自带安装入口。
| 目标 | Chromium 事件路径 | 无事件路径 |
|---|---|---|
| 显示页内安装操作 | 收到 beforeinstallprompt 后显示 |
保持隐藏 |
| 打开浏览器确认界面 | 在点击处理中调用已保存事件的 prompt() |
说明浏览器从哪里提供安装入口 |
| 移除失效推广 | 处理 appinstalled,使用后清除事件 |
页面加载时重新检查已安装显示模式 |
| 处理用户拒绝 | 隐藏控件,等待新的事件 | 没有可读取的提示结果 |
横幅在 HTML 中默认隐藏。只有浏览器向页面交付有效事件对象后,JavaScript 才显示它。
检测运行时支持
链接到“检测运行时支持”一节等待 beforeinstallprompt 前,先检测窗口是否有对应的事件处理器属性。支持该事件时,安装按钮保持隐藏,直到事件触发;不支持时,代码改为显示浏览器安装说明。BCD 未记录 Firefox 或 Safari 支持 BeforeInstallPromptEvent。
<button data-event-install type="button" hidden>安装</button><p data-event-fallback hidden>如果浏览器提供安装命令,请从浏览器界面使用该命令。</p>
<script> var installButton = document.querySelector('[data-event-install]'); var installFallback = document.querySelector('[data-event-fallback]');
if ('onbeforeinstallprompt' in window) { window.addEventListener('beforeinstallprompt', function (event) { event.preventDefault(); installButton.hidden = false; }); } else { installButton.hidden = true; installFallback.hidden = false; }</script>下一个示例会为支持分支补上点击处理器和提示流程。
把安装提示延后到横幅点击
链接到“把安装提示延后到横幅点击”一节下面是完整的 HTML 示例。它把浏览器事件保留到用户点击,从支持范围更广的 userChoice Promise 读取结果,不会解引用 prompt() 的返回值;appinstalled 触发时也会撤下横幅。
<aside data-install-banner hidden> <p>安装此应用,以便更快打开。</p> <button type="button">安装</button></aside><p><output data-install-status aria-live="polite"></output></p>
<script> (function () { var installEvent = null; var banner = document.querySelector('[data-install-banner]'); var status = document.querySelector('[data-install-status]'); var installButton = banner && banner.querySelector('button'); if (!banner || !status || !installButton) return;
window.addEventListener('beforeinstallprompt', function (event) { event.preventDefault(); installEvent = event; installButton.disabled = false; banner.hidden = false; });
installButton.addEventListener('click', function () { if (!installEvent) return; var pendingEvent = installEvent; installEvent = null; installButton.disabled = true;
pendingEvent.prompt().then(function () { return pendingEvent.userChoice; }).then(function (choice) { status.textContent = '安装提示结果:' + choice.outcome; banner.hidden = true; }, function (error) { status.textContent = '无法打开安装提示:' + error.name; banner.hidden = true; }); });
window.addEventListener('appinstalled', function () { installEvent = null; banner.hidden = true; status.textContent = '应用已安装。'; }); }());</script>按钮保持隐藏,直到事件真正触发;仅检测到属性不会改变这个状态。这使界面与浏览器对本次访问的判定保持一致。
处理没有事件的浏览器
链接到“处理没有事件的浏览器”一节失败路径会选择帮助说明,不会等待 BCD 在 Firefox 或 Safari 中未记录的事件。应用以 standalone 模式打开后,检查结果会隐藏说明。
<p data-install-help hidden> 如果浏览器提供安装命令,请从浏览器界面使用该命令。</p><p data-installed-state hidden>此应用已经作为已安装应用打开。</p>
<script> var help = document.querySelector('[data-install-help]'); var installedState = document.querySelector('[data-installed-state]'); var installed = window.matchMedia('(display-mode: standalone)').matches;
if (help && installedState) { installedState.hidden = !installed; help.hidden = installed || 'onbeforeinstallprompt' in window; }</script>回退分支没有 BeforeInstallPromptEvent,所以不调用 prompt()。应根据已测试的浏览器界面调整提示文字。安装提示兼容性数据给出引擎层面的支持差异,iOS 安装 API 实验记录则单独保存实测行为。
更正(2026-10-31)
链接到“更正(2026-10-31)”一节此次更正使 "accepted" 结果的说明与引用来源保持一致。MDN 的 prompt() 参考将 "accepted" 定义为用户安装了应用,web.dev 的应用内安装指南说明 userChoice 可报告用户是否通过应用内界面完成安装。原 publishedAt 日期保持不变。
另请参阅
链接到“另请参阅”一节- Manifest Incubations:安装提示(wicg.github.io)
- 提供应用内安装体验(web.dev)
- beforeinstallprompt 事件
- 安装提示 UX
- iOS 添加到主屏幕
规范
| 规范 | 状态 |
|---|---|
| 安装提示(beforeinstallprompt) | WICG 草案 |
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Desktop)# | 支持 | 44 | 高 | 来源 | — |
| Chrome (Android)# | 支持 | 44 | 高 | 来源 | 1 |
| Edge (Desktop)# | 支持 | 79 | 高 | 来源 | 2 |
| Firefox (Desktop)# | 不支持 | — | 高 | 来源 | 3 |
| Firefox (Android)# | 不支持 | — | 高 | 来源 | 45 |
| Safari (macOS)# | 不支持 | — | 高 | 来源 | 6 |
| Safari (iOS)# | 不支持 | — | 高 | 来源 | 78 |
| Samsung Internet# | 支持 | 5.0 | 高 | 来源 | — |
| WebView (Android)# | 支持 | 44 | 高 | 来源 | 9 |
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- 由 browser-compat-data 镜像自 Chrome 的数据推导。
- browser-compat-data 未记录 Firefox 的支持。
- browser-compat-data 未记录 Firefox for Android 的支持。
- 由 browser-compat-data 镜像自 Firefox 的数据推导。
- browser-compat-data 未记录 Safari 的支持。
- browser-compat-data 未记录 iOS 版 Safari 的支持。
- 由 browser-compat-data 镜像自 Safari 的数据推导。
- 由 browser-compat-data 镜像自 Chrome Android 的数据推导。
在线试用
在 OpenPWA 演示应用中运行此能力: /demo/#install