Firefox 158 的 navigate 选项:通知点击后浏览器自己跳,不用再写 notificationclick

Web 通知一直有个没说破的约定:收到 push → showNotification → 用户点击 → 触发 notificationclick → 你在 Service Worker 里 openWindow。这条链路里,跳转目标其实早就在通知里确定了,可你还是要写一整个事件处理器把它取出来、再手动跳。

Firefox 158 给 Notification 加了一个 navigate 选项,把中间那一整段省掉了:构造通知时直接把 URL 交给浏览器,用户激活通知后浏览器自己导航,click / notificationclick 都不再触发。

老写法为什么要写这么多

推送分两种,跳转逻辑也跟着分叉:

  • 页面内 new Notification(...) 弹的(非持久化),点击走 click 事件;
  • Service Worker 里 showNotification(...) 弹的(持久化),点击走 notificationclick,还得 event.waitUntil(clients.openWindow(url))。

SW 里的典型实现:

self.addEventListener("push", (event) => {
  const d = event.data.json();
  event.waitUntil(
    self.registration.showNotification(d.title, {
      body: d.body,
      data: { url: d.url },
      tag: "msg",
    })
  );
});

self.addEventListener("notificationclick", (event) => {
  event.notification.close();
  const url = event.notification.data.url;
  event.waitUntil(
    clients.matchAll({ type: "window" }).then((list) => {
      for (const c of list) if (c.url === url && "focus" in c) return c.focus();
      return clients.openWindow(url);
    })
  );
});

两个高频翻车点:URL 塞进 data 忘了取、matchAll 的匹配条件写歪,结果就是「通知点了但页面不动」。

新写法:URL 直接交给浏览器

Firefox 158 起加 navigate 即可,页面和 SW 同一种写法:

// 页面内
new Notification("Alice 发来一条消息", {
  body: "中午一起吃饭?",
  navigate: "/messages/alice",
});

// Service Worker 内
self.registration.showNotification("Alice 发来一条消息", {
  body: "中午一起吃饭?",
  navigate: "/messages/alice",
});

几个要点:

  • navigate 的值相对页面 base URL 解析,可以写相对路径;
  • 设置了它之后,用户激活通知时浏览器直接导航,不再触发 click 或 notificationclick;
  • 该属性在 Web Worker 中可用;
  • 只读属性 Notification.navigate 返回解析后的绝对 URL,没设置时是空串,可用来在代码里确认。

前后对照:

  • 过去:弹通知(带 data.url)→ 用户点击 → 触发事件 → 处理器取 URL → openWindow 或 focus → 跳转。跨页面和 SW 两套写法,至少 5 步。
  • 现在:弹通知(带 navigate)→ 用户点击 → 浏览器导航。1 步,同一套写法,也不再有「URL 存在 data 里没取出来」这种失败模式。

对「点了就去某页」的资讯推送、消息提醒,这能直接删掉一段易错代码。要点完先埋点、或按状态决定聚焦已有窗口还是开新窗口的复杂场景,仍应继续用事件处理器。

落地建议

  1. 翻一遍现有的 notificationclick:如果里面只是「取 data.url → openWindow/focus」,直接用 navigate 选项替换,删掉这段 SW 代码。
  2. 路径写法注意:相对路径按页面 base URL 解析,跨域跳转给绝对 URL。
  3. 兼容与降级:navigate 目前是实验性特性,仅 Firefox 158(Nightly)先行支持。上线保留 notificationclick 兜底,用 if ("navigate" in Notification.prototype) 决定走哪条路径。

(navigate 属实验性 API,生产环境务必保留事件处理器兜底。)

评论区

0 条评论

登录后可评论。

阿跨·跨端开发 1271 阅读