1. 术语
本规范依赖于 Infra 标准。[INFRA]
本规范中使用的一些术语在 DOM、Fetch、高分辨率时间、HTML、IDL、服务工作者、URL 和振动 API 标准中定义。[DOM] [FETCH] [HR-TIME] [HTML] [WEBIDL] [SERVICE-WORKERS] [URL] [VIBRATION]
2. 通知
通知是某些事件发生的抽象表示,例如消息的传递。
一个通知有一个关联的服务工作者注册(为空或为服务工作者注册)。它最初为空。
一个通知有一个关联的标题(一个字符串)。
一个通知有一个关联的方向("auto
"、"ltr
"或"rtl
")。
一个通知有一个关联的语言(一个字符串)。
一个通知有一个关联的内容(一个字符串)。
一个通知有一个关联的标签(一个字符串)。
一个通知有一个关联的时间戳(EpochTimeStamp
)。
时间戳可用于指示通知的实际时间。例如,当设备离线时无法立即传递消息,或用于即将开始的会议。
一个通知有一个关联的重新通知偏好(一个布尔值)。初始值为 false。当为 true 时,表示在运行通知显示步骤后,若有相同标签的现有通知,则应提醒用户。
一个通知有一个关联的静音偏好(为空或布尔值)。初始为 null。当为 true 时,表示不应发出声音或振动。当为 null 时,表示是否发出声音或振动应依赖平台惯例。
一个通知有一个关联的需要交互偏好(一个布尔值)。初始值为 false。当为 true 时,表示在具有足够大屏幕的设备上,通知应保持可用状态,直到用户激活或关闭该通知。
一个通知可以有以下相关图形:图片 URL、图标 URL和徽章 URL;以及相应的图片资源、图标资源和徽章资源。
图片资源是显示在通知内容中的图片,应优先显示于图标资源和徽章资源之上,尽管其显示情况可能更少。
图标资源是用于加强通知的图片(例如图标或发件人的照片)。
徽章资源是用于表示网络应用程序或通知类别的图标,如果网络应用程序发送多种通知。当没有足够空间显示通知时,可以使用它来表示通知。也可以在通知内部显示,但应优先于图片资源和图标资源。
开发者被鼓励不要通过图片、图标、徽章或振动模式传递无法被最终用户访问的信息,特别是因为不支持这些功能的通知平台可能会忽略它们。
一个通知有相关的操作(列表,零个或多个操作)。操作代表用户的选择。每个操作有一个关联的:
- 名称
- 一个字符串。
- 标题
- 一个字符串。
- 图标 URL
- 为空或URL。初始为 null。
- 图标资源
- 为空或为资源。初始为 null。
用户可以激活操作,作为激活通知本身的替代方式。支持的最大操作数是一个实现定义的零或更多整数,具体取决于通知平台的限制。
由于操作的显示是平台依赖的,开发者被鼓励确保用户可以从通知中调用的任何操作在网络应用程序内也可以使用。
某些平台可能会修改图标资源以更好地匹配平台的视觉风格,例如通过圆角或将其绘制成特定颜色。开发者被鼓励使用能够优雅处理这些情况的图标,并确保不会因为颜色丢失或角落被剪切而丢失重要信息。
要使用设置对象创建通知,给定字符串title,NotificationOptions
字典options,以及环境设置对象settings:
要创建通知,给定字符串title,NotificationOptions
字典options,origin origin,URL
baseURL,以及EpochTimeStamp
fallbackTimestamp:
-
让notification成为新的通知。
-
如果options["
silent
"]为true,且options["vibrate
"]存在,则抛出一个TypeError
。 -
如果options["
renotify
"]为true,且options["tag
"]为空字符串,则抛出一个TypeError
。 -
将notification的数据设置为StructuredSerializeForStorage(options["
data
"])。 -
将notification的标题设置为title。
-
将notification的来源设置为origin。
-
如果options["
image
"]存在,则使用baseURL解析它,若不返回失败,则将notification的图片URL设置为返回值。(否则不设置notification的图片URL。) -
如果options["
icon
"]存在,则使用baseURL解析它,若不返回失败,则将notification的图标URL设置为返回值。(否则不设置notification的图标URL。) -
如果options["
badge
"]存在,则使用baseURL解析它,若不返回失败,则将notification的徽章URL设置为返回值。(否则不设置notification的徽章URL。) -
如果options["
timestamp
"]存在,则将notification的时间戳设置为该值。否则,将notification的时间戳设置为fallbackTimestamp。 -
将notification的需要交互偏好设置为options["
requireInteraction
"]。 -
将notification的动作设置为« »。
-
返回notification。
2.1. 生命周期和UI集成
用户代理必须保留一个通知列表,这是一个列表,包含零个或多个通知。
用户代理不应当在平台的“通知中心”(如果有)中显示非持久性通知。
一个持久性通知可以调用其close()
方法中的某个Notification
对象。
用户代理应当在平台的“通知中心”(如果有)中显示持久性通知。
2.2. 权限集成
通知API是一个强大功能,其标识符为名称
“notifications
”。[Permissions]
要获取通知权限状态,请执行以下步骤:
-
将permissionState设为获取当前权限状态的结果,使用“
notifications
”。 -
如果permissionState是“
prompt
”,则返回“default
”。 -
返回permissionState。
2.3. 方向
本节内容的术语与HTML渲染部分中使用的术语等效。[HTML]
用户代理应遵守通知的标题、正文以及其每个动作的标题的Unicode语义。每个在显示时都应作为一组独立的双向算法段落处理,遵循双向算法规则P1、P2和P3,包括例如支持U+000A换行符(LF字符)的段落断开行为。对于每个标题、正文及其动作的标题的段落,如果通知的方向值不是“auto
”,则其提供了对规则P2和P3的高级覆盖。[BIDI]
通知的方向还决定了通知的动作应如何展示给终端用户的相对顺序,如果通知平台并排显示这些动作的话。
2.4. 语言
通知的notification的language指定通知的主要语言,包括通知的标题、正文和每个动作的标题。其值为字符串。空字符串表示主要语言未知,任何其他字符串必须解释为语言标签。有效性或格式的正确性不受强制。[BCP47]
建议开发者只使用有效的语言标签。
2.5. 资源
给定通知notification的fetch steps:
-
如果通知平台支持图片,fetch notification的image URL(如果已设置)。
然后,并行:
-
等待响应。
-
如果支持该图像格式,则将notification的image resource设置为解码后的资源。(否则notification没有image resource。)
-
-
如果通知平台支持图标,fetch notification的icon URL(如果已设置)。
然后,并行:
-
等待响应。
-
如果支持该图像格式,则将notification的icon resource设置为解码后的资源。(否则notification没有icon resource。)
-
-
如果通知平台支持徽章,fetch notification的badge URL(如果已设置)。
然后,并行:
-
等待响应。
-
如果支持该图像格式,则将notification的badge resource设置为解码后的资源。(否则notification没有badge resource。)
-
-
如果通知平台支持动作和动作图标,则对于每个action,在notification的actions中:如果icon URL非空,fetch该action的icon URL。
然后,并行:
-
等待响应。
-
如果支持该图像格式,则将action的icon resource设置为解码后的资源。(否则action的icon resource保持为空。)
-
2.6. 显示通知
给定通知notification的notification show steps如下:
-
运行notification的fetch steps。
-
等待任何fetches完成,并设置notification的image resource、icon resource和badge resource(如果有),以及notification的动作的icon resources(如果有)。
-
设置shown为false。
-
设置oldNotification为通知,从通知列表中找到tag不是空字符串且与notification的tag相同,且其origin与notification的origin相同的通知(如果有),否则为null。
-
如果oldNotification非空,则:
-
如果shown为false,则:
-
如果shown为false或oldNotification非空,且notification的renotify偏好为true,则为notification运行提醒步骤。
-
如果notification是非持久性通知,则排队一个任务,触发一个事件,名为
show
,在表示notification的Notification
对象上。
2.7. 激活通知
当用户激活通知 notification或其中的一个动作时,假设底层通知平台支持激活,用户代理必须(除非另有说明)执行以下步骤:
-
如果notification是持久性通知,则:
-
设置action为空字符串。
- 触发一个名为
notificationclick
的服务工作者通知事件,给定notification和action。
-
-
否则,排队一个任务以运行以下步骤:
-
设置intoFocus为触发一个名为
click
的事件,在表示notification的Notification
对象上,且其cancelable
属性被初始化为true。鼓励用户代理使
focus()
在事件监听器中工作, 针对名为click
的事件。 -
如果intoFocus为true,则用户代理应将notification的相关浏览上下文的视口聚焦。
-
在整个web平台上,“激活”被故意错误命名为“点击”。
2.8. 关闭通知
给定通知notification的关闭步骤如下:
给定通知notification,处理关闭事件如下:
-
如果notification是持久性通知,且notification被终端用户关闭,则触发一个服务工作者通知事件,名为"
notificationclose
",给定notification。 -
如果notification是非持久性通知,则排队一个任务,触发一个事件名为
close
,在表示notification的Notification
对象上。
2.9. 提醒终端用户
3. API
[Exposed =(Window ,Worker )]interface :
Notification EventTarget {constructor (DOMString ,
title optional NotificationOptions = {});
options static readonly attribute NotificationPermission permission ; [Exposed =Window ]static Promise <NotificationPermission >requestPermission (optional NotificationPermissionCallback );
deprecatedCallback static readonly attribute unsigned long maxActions ;attribute EventHandler onclick ;attribute EventHandler onshow ;attribute EventHandler onerror ;attribute EventHandler onclose ;readonly attribute DOMString title ;readonly attribute NotificationDirection dir ;readonly attribute DOMString lang ;readonly attribute DOMString body ;readonly attribute DOMString tag ;readonly attribute USVString image ;readonly attribute USVString icon ;readonly attribute USVString badge ; [SameObject ]readonly attribute FrozenArray <unsigned long >vibrate ;readonly attribute EpochTimeStamp timestamp ;readonly attribute boolean renotify ;readonly attribute boolean ?silent ;readonly attribute boolean requireInteraction ; [SameObject ]readonly attribute any data ; [SameObject ]readonly attribute FrozenArray <NotificationAction >actions ;undefined close (); };dictionary {
NotificationOptions NotificationDirection = "auto";
dir DOMString = "";
lang DOMString = "";
body DOMString = "";
tag USVString ;
image USVString ;
icon USVString ;
badge VibratePattern ;
vibrate EpochTimeStamp ;
timestamp boolean =
renotify false ;boolean ?=
silent null ;boolean =
requireInteraction false ;any =
data null ;sequence <NotificationAction >= []; };
actions enum {
NotificationPermission ,
"default" ,
"denied" };
"granted" enum {
NotificationDirection ,
"auto" ,
"ltr" };
"rtl" dictionary {
NotificationAction required DOMString ;
action required DOMString ;
title USVString ; };
icon callback =
NotificationPermissionCallback undefined (NotificationPermission );
permission
A 非持久性通知由一个Notification
对象表示,并可以通过Notification
的
构造函数创建。
A 持久性通知由零个或多个Notification
对象表示,并可以通过showNotification()
方法创建。
3.1. 垃圾回收
Notification
对象在通知列表包含其对应的通知并且它有一个类型为click
、show
、close
或
error
的事件监听器时,不能被垃圾回收。
3.2. 构造函数
new Notification(title, options)
构造函数的步骤如下:
3.3. 静态成员
静态permission
获取器步骤是返回获取通知权限状态的结果。
如果你编辑标准,请避免复制上面的内容。同步权限就像同步IO,是一个糟糕的想法。
建议开发者使用权限query()
方法代替。[Permissions]
const permission = await navigator.permissions.query({name: "notifications"}); if (permission.state === "granted") { // 我们有权限使用API… }
静态requestPermission(deprecatedCallback)
方法步骤如下:
-
令global为当前全局对象。
-
令promise为一个新的 promise,位于this的相关领域中。
-
并行运行以下步骤:
-
返回promise。
通知是目前为止唯一一个在请求用户权限时有意义的实例。其他API的规范不应使用这种模式,而应采用更多合适的替代方案之一。
静态maxActions
获取器步骤是返回支持的最大操作数。
3.4. 对象成员
以下是 事件处理器(及其对应的 事件处理器事件类型),必须作为 Notification
对象的属性支持。
事件处理器 | 事件处理器事件类型 |
---|---|
onclick
| click
|
onshow
| show
|
onerror
| error
|
onclose
| close
|
close()
方法的步骤是运行 关闭步骤,应用于 this 的 通知。
title
的 getter 步骤是返回 this 的 通知的 标题。
dir
的 getter 步骤是返回 this 的 通知的 方向。
lang
的 getter 步骤是返回 this 的 通知的 语言。
body
的 getter 步骤是返回 this 的 通知的 正文。
tag
的 getter 步骤是返回 this 的 通知的 标签。
image
的 getter 步骤是:
icon
的 getter 步骤是:
badge
的 getter 步骤是:
vibrate
的 getter 步骤是返回 this 的 通知的
振动模式。
timestamp
的 getter 步骤是返回 this 的 通知的
时间戳。
renotify
的 getter 步骤是返回 this 的 通知的
重新通知偏好。
silent
的 getter 步骤是返回 this 的 通知的
静音偏好。
requireInteraction
的 getter 步骤是
返回 this 的 通知的
需要互动偏好。
data
的 getter 步骤是返回 StructuredDeserialize(this 的 通知的 数据,this 的 相关 Realm)。如果这会抛出异常,则返回 null。
actions
的 getter 步骤是:
-
让 frozenActions 成为类型
NotificationAction
的空列表。 -
-
让 action 成为一个新的
NotificationAction
。 -
如果 entry 的 图标 URL 不为 null,则将 action["
icon
"] 设置为 entry 的 图标 URL,序列化后返回。 -
调用 Object.freeze 于 action 上, 防止脚本意外更改。
-
将 action 添加到 frozenActions。
-
-
返回 创建一个冻结数组 的结果,来源于 frozenActions。
3.5. Examples
3.5.1. Using events from a page
非持久化 Notification
对象在其生命周期内调度事件,开发人员可以利用这些事件生成所需的行为。
当最终用户激活通知时,click
事件将被调度。
var not = new Notification("Gebrünn Gebrünn by Paul Kalkbrenner", { icon: "newsong.svg", tag: "song" }); not.onclick = function() { displaySong(this); };
3.5.2. Using actions from a service worker
持久化通知 在
ServiceWorkerGlobalScope
上触发 notificationclick
事件。
在此,服务工作线程显示带有单个 "存档" 操作 的通知,允许最终用户在不打开网站的情况下执行此常见任务(例如,通知平台可能在通知上显示一个按钮)。最终用户还可以激活通知的主要部分以打开他们的收件箱。
self.registration.showNotification("New mail from Alice", { actions: [{action: 'archive', title: "Archive"}] }); self.addEventListener('notificationclick', function(event) { event.notification.close(); if (event.action === 'archive') { silentlyArchiveEmail(); } else { clients.openWindow("/inbox"); } }, false);
3.5.3. 使用 tag
成员来处理多个实例
Web 应用程序通常在多个实例中并行运行,例如当最终用户在多个浏览器选项卡中打开邮件应用程序时。由于桌面是共享资源,通知 API 提供了一种方法,使这些实例可以轻松协调,通过使用 tag
成员。
代表同一概念事件的通知可以以相同的方式进行标记,当两者显示时,最终用户只会收到一个通知。
实例 1 | 实例 2 | // 实例注意到有新邮件。 | new Notification("New mail from John Doe", | { tag: 'message1' }); | | | // 稍后,此实例注意到有新邮件。 | new Notification("New mail from John Doe", | { tag: 'message1' });
如果用户代理遵循此处的算法,这种情况下的结果是一个 单一 通知 "来自 John Doe 的新邮件"。
3.5.4. 使用 tag
成员来处理单个实例
tag
成员还可以由单个实例的应用程序使用,以便在状态更改时保持其通知尽可能最新。
例如,如果 Alice 正在使用聊天应用程序与 Bob 聊天,而 Bob 在 Alice 闲置时发送了多条消息,应用程序可能希望 Alice 不会看到每条消息的桌面通知。
// Bob 说 "Hi" new Notification("Bob: Hi", { tag: 'chat_Bob' }); // Bob 说 "你今天下午有空吗?" new Notification("Bob: Hi / 你今天下午有空吗?", { tag: 'chat_Bob' });
这种情况下的结果是一个 单一 通知;第二个通知替换了具有相同标签的第一个。在排队通知(先进先出)的平台中,使用标签还允许通知保持其在队列中的位置。在显示最新通知优先的平台上,类似的结果可以通过使用
close()
方法实现。
4. Service worker API
dictionary {
GetNotificationOptions DOMString = ""; };
tag partial interface ServiceWorkerRegistration {Promise <undefined >showNotification (DOMString ,
title optional NotificationOptions = {});
options Promise <sequence <Notification >>getNotifications (optional GetNotificationOptions = {}); }; [
filter Exposed =ServiceWorker ]interface :
NotificationEvent ExtendableEvent {(
constructor DOMString ,
type NotificationEventInit );
eventInitDict readonly attribute Notification notification ;readonly attribute DOMString action ; };dictionary :
NotificationEventInit ExtendableEventInit {required Notification ;
notification DOMString = ""; };
action partial interface ServiceWorkerGlobalScope {attribute EventHandler onnotificationclick ;attribute EventHandler onnotificationclose ; };
showNotification(title, options)
方法的步骤为:
-
将 promise 设为 一个新的 promise,位于 this 的 相关领域中。
-
如果 this 的 激活的 worker 为 null,则拒绝 promise 并抛出
TypeError
,并返回 promise。 -
将 notification 设为 使用设置对象创建通知的结果,给定 title、 options 以及 this 的 相关设置对象。如果此操作抛出异常,则 拒绝 promise 并返回 promise。
-
并行运行以下步骤:
-
返回 promise。
getNotifications(filter)
方法的步骤为:
-
将 promise 设为 一个新的 promise,位于 realm。
-
并行运行以下步骤:
-
返回 promise。
此方法返回 0 或更多新的 Notification
对象,这些对象可能代表已经存在的 相同底层通知。
为了触发名为 name 的 service worker 通知事件,给定 通知
notification,以及可选的字符串
action(默认为空字符串),运行 Fire Functional Event,给定 name、NotificationEvent
、notification 的 service worker 注册,并初始化如下:
notification
- 一个新的
Notification
对象,代表 notification。 action
- action
notification
getter 的步骤是返回它初始化的值。
action
getter 的步骤是返回它初始化的值。
以下是 事件处理器(及其对应的 事件类型),必须作为属性被 ServiceWorkerGlobalScope
对象支持:
事件处理器 | 事件类型 |
---|---|
onnotificationclick
|
notificationclick |
onnotificationclose
|
notificationclose |
致谢
感谢 Addison Phillips, Aharon (Vladimir) Lanin, Alex Russell, Anssi Kostiainen, Arkadiusz Michalski, Boris Zbarsky, David Håsäther, Doug Turner, Drew Wilson, Ehsan Akhgari, Frederick Hirsch, Ian Hickson, Jake Archibald, James Graham, John Mellor, Jon Lee, Jonas Sicking, Michael Cooper, Michael Henretty, Michael™ Smith, Michael van Ouwerkerk, Mike Taylor, Nicolás Satragno, Olli Pettay, Peter Beverloo, Philip Jägenstedt, Reuben Morais, Rich Tibbett, Robert Bindar, 박상현 (Sanghyun Park), Simon Pieters, Theresa O’Connor, timeless, and triple-underscore for being awesome.
本标准由 Anne van Kesteren (Apple, annevk@annevk.nl) 撰写。早期版本由 John Gregg (Google, johnnyg@google.com) 撰写。
知识产权
版权所有 © WHATWG (Apple, Google, Mozilla, Microsoft)。本作品采用 知识共享署名 4.0 国际许可协议 授权。若本作品的部分内容被纳入源代码中,则该部分内容在源代码中依据 BSD 3-Clause License 授权。
这是现行标准。对于专利审查版本感兴趣的人员,应查看 现行标准 审查草案。