窗口管理

浏览器外的 PWA 会管理自己的窗口。在本章中,您将了解用于管理操作系统中的窗口的 API 和功能。

PWA 窗口

在由 PWA 管理的自有窗口中运行,具有该操作系统中任何窗口的所有优势和责任,例如:

  • 在多窗口操作系统(例如 Windows 或 ChromeOS)上调整窗口大小和移动窗口。
  • 与其他应用窗口共享屏幕,例如在 iPadOS 分屏模式或 Android 分屏模式下。
  • 在桌面设备上的程序坞、任务栏和 Alt-Tab 菜单中展示,在移动设备上显示在多任务窗口列表中。
  • 能够最小化窗口,跨屏幕和桌面移动窗口,以及随时将其关闭。

移动和调整窗口大小

在桌面操作系统上,您的 PWA 窗口可以是任意大小,并且可以放置在屏幕上的任意位置。默认情况下,当用户在安装后首次打开 PWA 时,PWA 的默认窗口大小为当前屏幕的百分比,最大分辨率为 1920x1080,位于屏幕的左上角。

用户可以移动和调整窗口大小,浏览器会记住上次的偏好设置,因此当用户下次打开应用时,窗口将保留上次使用时的大小和位置。

您无法在清单中定义 PWA 的首选大小和位置。您只能使用 JavaScript API 调整窗口的位置和大小。您可以在代码中使用 window 对象的 moveTo(x, y)resizeTo(x, y) 函数移动和调整自己的 PWA 窗口的大小。

例如,您可以在 PWA 加载时使用以下方法调整 PWA 窗口的大小和移动窗口:

document.addEventListener("DOMContentLoaded", event => {
   // we can move only if we are not in a browser's tab
   isBrowser = matchMedia("(display-mode: browser)").matches;
   if (!isBrowser) {
      window.moveTo(16, 16);
      window.resizeTo(800, 600);
   }
});

您可以使用 window.screen 对象查询当前屏幕尺寸和位置;您可以使用 window 对象中的 resize 事件检测窗口何时调整大小。没有用于捕获窗口移动的事件,因此您可以选择频繁查询位置。

浏览其他网站

如果您想将用户定向到超出 PWA 范围的外部网站,可以使用标准 <a href> HTML 元素、使用 location.href 或在兼容平台上打开新窗口来实现此目的。

目前,在所有浏览器中,如果您已安装 PWA,当您浏览超出清单范围的网址时,PWA 的浏览器引擎将在窗口上下文中呈现应用内浏览器。

应用内浏览器的部分功能如下:

  • 它们会显示在内容上方。
  • 它们有一个静态网址栏,用于显示当前来源、窗口标题和菜单。通常,它们采用清单的 theme_color 主题。
  • 通过上下文菜单,您可以在浏览器中打开该网址。
  • 用户可以关闭浏览器或返回。

在桌面 PWA 中浏览超出范围的网址时,应用内浏览器。

在独立 PWA 中浏览不在服务范围内的网址时,iPhone 上的应用内浏览器。

在 Android 设备上浏览独立 PWA 范围之外的网址时,使用应用内浏览器。

授权流程

许多网络身份验证和授权流程都涉及将用户重定向到其他来源中的其他网址,以获取将返回到 PWA 来源的令牌(例如使用 OAuth 2.0)。

在这些情况下,应用内浏览器会遵循以下流程:

  1. 用户打开您的 PWA 并点击“登录”。
  2. 您的 PWA 会将用户重定向到超出 PWA 范围的网址,以便呈现引擎在 PWA 中打开应用内浏览器。
  3. 用户可以随时取消应用内浏览器并返回到您的 PWA。
  4. 用户登录应用内浏览器。身份验证服务器会将用户重定向到您的 PWA 源,并将令牌作为参数发送。
  5. 当应用内浏览器检测到属于 PWA 范围内的网址时,会自行关闭。
  6. 引擎会将主要 PWA 窗口导航重定向到身份验证服务器在应用内浏览器中访问的网址。
  7. 您的 PWA 会获取令牌、存储令牌并呈现 PWA。

强制浏览器导航

如果您想使用网址(而不是应用内浏览器)强制打开浏览器,则可以使用 <a href> 元素的 _blank 目标。此功能仅适用于桌面版 PWA;在移动设备上,没有使用网址打开浏览器的选项。

function openBrowser(url) {
    window.open("url", "_blank", "");
}

打开新窗口

在桌面设备上,用户可以在同一 PWA 中打开多个窗口。每个窗口都会是指向同一 start_url 的不同导航,就像您打开了两个指向同一网址的浏览器标签页一样。在 PWA 的菜单中,用户可以依次选择“File”(文件)和“New window”(新窗口),而在 PWA 代码中,您可以使用 open() 函数打开新窗口。如需了解详情,请参阅文档

function openNewWindow() {
    window.open("/", "new-window", "width=600,height=600");
}

在桌面操作系统上打开多个窗口的同一已安装 PWA。

在 iOS 或 iPadOS 上的 PWA 窗口中调用 open() 会返回 null,并且不会打开窗口。在 Android 设备上打开新窗口会为网址创建新的应用内浏览器,即使网址在 PWA 的范围内,通常也不会触发外部浏览体验。

窗口标题

由于浏览器标签页中的空间有限,因此 <title> 元素主要用于 SEO 目的。当您从浏览器切换到 PWA 窗口时,您可以使用标题栏的所有空间。

您可以定义标题栏的内容:

  • 在 HTML <title> 元素中以静态方式。
  • 随时动态更改 document.title 字符串属性。

在桌面 PWA 中,标题至关重要,它会显示在窗口的标题栏中,有时还会显示在任务管理器或多任务选择中。如果您使用的是单页应用,则可能需要更新每个路线的标题。

标签页模式

一种名为标签页式模式的实验性功能可让您的 PWA 采用类似于网络浏览器的标签页式设计。在这种情况下,用户可以从同一 PWA 打开多个标签页,但所有标签页都绑定在同一操作系统窗口中,如以下视频所示:

如需详细了解这项实验性功能,请参阅 PWA 的标签式应用模式

窗口控件叠加层

我们曾提到,您可以通过定义 <title> 元素或 document.title 属性的值来更改窗口的标题。但它始终是字符串值。如果我们可以使用 HTML、CSS 和图片来按照自己的意愿设计标题栏,结果会怎样? 这时,窗口控件叠加层就派上用场了。这是 Microsoft Edge 和 Google Chrome 针对桌面版 PWA 推出的一项全新实验性功能。

如需详细了解此功能,请参阅自定义 PWA 标题栏的窗口控件叠加层

借助窗口控件叠加层,您可以在标题栏中呈现内容。

窗口管理

在多屏设备上,用户会希望使用所有可用的空间。例如:

  • 类似于 Gimp 的多窗口图形编辑器可以将各种编辑工具放置在精确定位的窗口中。
  • 虚拟交易公司可通过多个窗口显示市场趋势,其中任一窗口均可在全屏模式下查看。
  • 幻灯片应用可以在内部主屏幕中显示演讲者备注,并在外部投影仪上显示演示文稿。

借助 Window Management API,PWA 能够执行此类操作,甚至更多。

获取屏幕详情

Window Management API 添加了一个新方法 window.getScreenDetails(),该方法会返回一个将屏幕作为附加屏幕的不可变数组的对象。还有一个可从 ScreenDetails.currentScreen 访问的实时对象,对应于当前的 window.screen

screens 数组发生变化时,返回的对象还会触发 screenschange 事件。(更改各个屏幕上的属性时不会出现这种情况。)当各个屏幕(window.screenscreens 数组中的屏幕)的属性发生更改时,也会触发 change 事件。

// Request an object with a screen objects
const screenDetails = await window.getScreenDetails();
screenDetails.screens[0].isPrimary;  // e.g. true
screenDetails.screens[0].isInternal;  // e.g. true
screenDetails.screens[0].label;  // e.g. 'Samsung Electric Company 28"'

// Access the live object corresponding to the current `window.screen`.
// The object is updated on cross-screen window placements or device changes.
screenDetails.currentScreen;
screenDetails.addEventListener('screenschange', function() {
 // NOTE: Does not fire on changes to attributes of individual screens.
  const screenCount = screenDetails.screens.length;
  const currentScreen screenDetails.currentScreen.id;
});

如果用户或操作系统将 PWA 的窗口从一个屏幕移动到另一个屏幕,系统也会从屏幕详细信息对象触发 currentscreenchange 事件

屏幕唤醒锁定

假设您在厨房里,按照平板电脑上的食谱做饭。您刚刚准备好了食材。您的双手一团糟,为了接着说下一句话,必须拿着设备看。惨了!屏幕变黑了!Screen Wake Lock API 可让 PWA 防止屏幕变暗、进入休眠状态或锁定,让用户可以放心地停止、启动、离开和返回。

// Request a screen wake lock
const wakeLock = await navigator.wakeLock.request();

// Listen for wake lock release
wakeLock.addEventListener('release', () => {
 console.log(`Screen Wake Lock released: ${wakeLock.released}`);
});
// Manually release the wake lock
wakeLock.release();

虚拟键盘

触控设备(例如手机和平板电脑)提供虚拟屏幕键盘,以便用户在 PWA 的表单元素获得焦点时输入内容。

借助 VirtualKeyboard API,您的 PWA 现在可以使用 navigator.virtualKeyboard 接口在兼容平台上更好地控制键盘,包括:

  • 使用 navigator.virtualKeyboard.show()navigator.virtualKeyboard.hide() 函数显示和隐藏虚拟键盘。
  • 通过将 navigator.virtualKeyboard.overlaysContent 设为 true,告知浏览器您将自行关闭虚拟键盘。
  • 通过 navigator.virtualKeyboard 的事件 geometrychange 获知键盘何时出现和消失。
  • 使用 virtualkeyboardpolicy HTML 属性在修改宿主元素(使用 contenteditable)时设置虚拟键盘政策。通过政策,您可以决定是让浏览器使用 auto 值自动处理虚拟键盘,还是让脚本使用 manual 值处理虚拟键盘。
  • 使用 CSS 环境变量获取有关虚拟键盘外观的信息,例如 keyboard-inset-heightkeyboard-inset-top

如需详细了解此 API,请参阅 Virtual 键盘 API 实现完全控制

资源