skip to content
寻找莉莉丝

浅尝浏览器桌面通知 Notification

/ 5 min read / 次阅读

参考:

一、前言

最近业务开发中,有一个需求,需要弹出桌面通知弹窗。

这是我从没做过的,所以开贴与大家分享一下,另外讲一下存在的问题。

image.png

二、Notification

2.1 通知实例

new Notification(title);
new Notification(title, options);
  • title:标题
  • options:配置(可选)

2.2 通知的配置

也是弹窗的组成部分:

  • image 通知弹窗的上方大图
  • icon 图标
  • requireInteraction 下方的关闭按钮(默认值为 false)
  • silent 通知声音静音(默认值为 false)
  • body 通知内容

等等。

const options = {
	image:
		"https://images.unsplash.com/photo-1623653387945-2fd25214f8fc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80",
	// body 正文部分最多显示 4 行
	body: `here the body (the first line)\nthe second line\nthe third line\nthe fourth line\nthe fifth line which cannot display\n`,
	icon: "https://images.unsplash.com/photo-1619380897562-725c909c68db?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1171&q=80",
	// Indicates that a notification should remain active until the user clicks or dismisses it, rather than closing automatically.
	requireInteraction: true,
	silent: true,
};

注意:

  • body 内容最多能显示 4 行。
  • image, icon 本地和远程的 url 都支持。
  • requireInteraction 默认为 false,会自动关闭通知。只有设置为 true 后,面板下方才能出现“关闭”按钮,此时监听通知的关闭事件才有效果;另外,设置为 true 后,这类弹窗无法自动关闭。
  • silent 默认为 false,设置为 true 后,就不会有系统提示音了,这个可以不用去系统里设置谷歌浏览器的通知声音,用这个属性就能解决。

三、可运行的代码

原功能比这个更加复杂,这里做了简化。

<!doctype html>
<html>
	<head>
		<title>浏览器通知</title>
	</head>
	<body>
		<button onclick="notifyMe()">Notify me!</button>
		<button onclick="mutiplyNotify()">Notify me! (mutiplyNotify)</button>

		<script>
			function generateNotification(title, options) {
				return new Notification(title, options);
			}

			function mutiplyNotify() {
				for (let i = 0; i < 3; i++) {
					notifyMe(i);
				}
			}

			function notifyMe(title = "") {
				console.log(title);
				let notification = null;
				const options = {
					image:
						"https://images.unsplash.com/photo-1623653387945-2fd25214f8fc?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80",
					// image: './bg.jpg',
					// body 正文部分最多显示 4 行
					body: `here the body (the first line)\nthe second line\nthe third line\nthe fourth line\nthe fifth line which cannot display\n`,
					icon: "https://images.unsplash.com/photo-1619380897562-725c909c68db?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1171&q=80",
					// icon: './th.jpg',
					// Indicates that a notification should remain active until the user clicks or dismisses it, rather than closing automatically.
					requireInteraction: true,
					silent: true,
				};

				// Let's check if the browser supports notifications
				if (!("Notification" in window)) {
					alert("This browser does not support desktop notification");
				}

				// Let's check whether notification permissions have already been granted
				else if (Notification.permission === "granted") {
					// If it's okay let's create a notification
					notification = generateNotification(`Hi there! I'm a title${title}.`, options);
				}

				// Otherwise, we need to ask the user for permission
				else if (Notification.permission !== "denied") {
					Notification.requestPermission().then(function (permission) {
						// If the user accepts, let's create a notification
						if (permission === "granted") {
							notification = generateNotification(`Hi there! I'm a title${title}.`, options);
						}
					});
				}

				// At last, if the user has denied notifications, and you
				// want to be respectful there is no need to bother them anymore.

				// when show
				notification.onshow = function () {
					console.log("when show");
				};
				// when click
				notification.onclick = function () {
					console.log("when click");
					window.open(window.location.href);
				};
				// when close
				notification.onclose = function () {
					console.log("when close");
				};
				// when error
				notification.onerror = function () {
					console.log("when error");
				};
			}
		</script>
	</body>
</html>

四、总结与风险点评估

Notification 将浏览器 API 与 windows 通知功能结合,作为通知用户的一种方式显得非常巧妙,仅仅是通知也比较合适。但过度的定制化,开发性价比是不高的,存在一些问题尚未解决或难以解决。

  1. 一次只能在右下角显示一个,无法叠加显示多个通知面板。

  2. 通过点击通知面板右上角的“x”图标关闭弹窗时,无法监听到点击事件、也无法监听到关闭事件。

  3. for循环依次新建通知面板时,通知面板的弹出顺序是乱序的,可能是因为线程不同导致的。 image.png

  4. 当用户将浏览器窗口最小化,想要实现点击通知回到原网页,似乎难以解决。

    但这里提供一个取巧的方案(https://developer.mozilla.org/zh-CN/docs/Web/API/Window/close),利用 window.open() 打开一个新标签页(newTab),然后立即再通过 window.close() 去关闭 newTab,让用户好像就回到了原网页一样。

    notification.onclick = function () {
      console.log('when click')
      window.open(window.location.href)
      const newTab = window.open(window.location.href)
      window.close('newTab')
    }
  5. 浏览器兼容性可能不太好

    image.png
  6. 为了确保安全,这个API只允许在 HTTPS 环境下使用,但是也可以通过特别的方式去设置,这里不赘述。