窗口管理

浏览器之外的 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 上浏览范围外网址时的应用内浏览器。

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

在 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 的菜单中依次选择“文件”和“新窗口”,然后,您可以在 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 标题栏的窗口控件叠加层

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

窗口管理

如果有多个屏幕,用户会希望充分利用可用的所有空间。例如:

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

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].pointerTypes;  // e.g. ["touch"]
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,您现在可以使用 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,请参阅使用 VirtualKeyboard API 进行完全控制

资源