我有以下使用Java脚本的测试html,其中主要感兴趣的是通知:

<head>
    <title>Test Notifications</title>

</head>
<body>


    <div >
        <button  style="margin: 0;position: absolute;top: 50%;left: 50%;-ms-transform: translate(-50%, -50%);transform: translate(-50%, -50%);" 
                 onclick="askPermissionsAndSendNotification();"  >Send Notification</button>

    </div>


    <script type="text/javascript"   >
        function askPermissionsAndSendNotification() {

            if (!window.Notification) {
                return false;
            } else {
                if (Notification.permission === 'default') {
                    Notification.requestPermission(function (p) {
                        if (p !== 'denied') {
                            sendNotification();
                        }
                    })
                } else {
                    sendNotification();
                }
            }
        }

        function sendNotification() {
            let title = "Test notification";
            let message = "Test notification content";
            let  myNotification = new Notification(title, {
                body: message
            });
            myNotification.addEventListener('click', function () {
                window.open("https://stackoverflow.com/","_blank");
            });
        }
    </script>

</body>

是一个简单的通知,我们通过点击按钮来发送它,并将打开一个带有URL的新选项卡.一切都很完美,直到刷新.

如果你有一个未关闭的通知,如果你刷新页面,无论你的点击事件中的代码是什么,通知都会打开一个新页面,其中包含你的网站基础URL.我假设监听程序在页面刷新时被销毁,这可能是默认行为.如果在刷新之前创建了通知,是否可以在页面刷新后调用原始的通知onClick操作?

推荐答案

浏览器中的通知是non-persistent,这会导致它们在您关闭选项卡时停止工作.您需要将您的逻辑转移到Service Worker才能使用persistent通知.安装后,无论选项卡处于打开还是关闭状态,服务工作人员都将运行.

首先注册您的服务工作者.然后修改sendNotification函数.我们希望让该功能向Service Worker发送一条消息,其中包含您的通知所需的信息,而不是创建Notification个自己,然后Worker将负责创建通知.

可以使用当前注册工作者的postMessage方法将消息发送给服务工作者.您还可以发送您希望用户在单击时重定向到的URL.

// app.js
navigator.serviceWorker.register('serviceworker.js');

async function sendNotification() {
  let title = "Test notification";
  let message = "Test notification content";
  const url = "https://stackoverflow.com/";

  // Wait until the Service Worker ready.
  const registration = await navigator.serviceWorker.ready;

  // Send a message over to the worker.
  registration.active.postMessage({
    title,
    message,
    url
  })
}

在服务工作者端,您首先希望能够接收我们从客户端发送的任何传入消息.侦听message事件并处理从那里接收到的数据.服务工作者注册有一个名为showNotification的内置方法,它的作用与new Notification()完全相同.将您的数据传递给该方法.

然后收听notificationclick事件.在这里,您可以处理用户单击通知时需要发生的任何事情.从这里,您可以访问url,并使用Clients界面的openWindow()方法打开一个新的浏览器窗口.

// serviceworker.js
addEventListener('message', ({ data }) => {
  // Deconstruct received data.
  const {
    title,
    message,
    url
  } = data;

  // Show notification with the received data.
  registration.showNotification(title, {
    body: message,
    data: {
      url
    }
  });
})

addEventListener('notificationclick', (event) => {
  event.notification.close();

  const { url } = event.notification.data;
  const openPage = clients.openWindow(url);
  event.waitUntil(openPage);
});

Javascript相关问答推荐

如何将拖放功能添加到我已自定义为图像的文件输入HTML标签中?

从实时数据库(Firebase)上的子类别读取数据

窗口.getComputedStyle()在MutationObserver中不起作用

react/redux中的formData在expressjs中返回未定义的req.params.id

格式值未保存在redux持久切片中

D3 Scale在v6中工作,但在v7中不工作

Angular material 拖放堆叠的牌副,悬停时自动展开&

如何从调整大小/zoom 的SVG路径定义新的d属性?""

扩展类型的联合被解析为基类型

在数组中查找重叠对象并仅返回那些重叠对象

JavaScript不重定向配置的PATH

按下单键和多值

我想将Sitecore搜索面过滤器从多个转换为单个

当我点击一个按钮后按回车键时,如何阻止它再次被点击

MongoDB通过数字或字符串过滤列表

我的NavLink活动类在REACT-ROUTER-V6中出现问题

如何正确地在ComponentWillUnmount中卸载状态以避免内存泄漏?

表单数据中未定义的数组键

正则表达式以确定给定文本是否不只包含邮箱字符串

在对象的嵌套数组中添加两个属性