一、前言
最近业务开发中,有一个需求,需要弹出桌面通知弹窗。
这是我从没做过的,所以开贴与大家分享一下,另外讲一下存在的问题。
二、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循环依次新建通知面板时,通知面板的弹出顺序是乱序的,可能是因为线程不同导致的。.
- 4.当用户将浏览器窗口最小化,想要实现点击通知回到原网页,似乎难以解决。
但这里提供一个取巧的方案(developer.mozilla.org/zh-CN/docs/…),利用 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.浏览器兼容性可能不太好
6.为了确保安全,这个API只允许在 HTTPS 环境下使用,但是也可以通过特别的方式去设置,这里不赘述。