Notification API,為你的網頁添加桌面通知推送

Notification 是什麼

MDN:

Notifications API 的 Notification 介面用於配置和向用戶顯示桌面通知。這些通知的外觀和特定功能因平台而異,但通常它們提供了一種向用戶非同步提供資訊的方式。

其實,MDN 的說明已經可以讓我們很清楚知道 Notification 的作用。Notification 能夠為用戶提供非同步的桌面消息通知,即使你縮小瀏覽器或是活動在其他標籤頁,只要調用該 Api 的標籤頁沒被關閉,它都能工作。在桌面端的瀏覽器中,除了 IE 不支援外,其他就均已支援。

以下只提到常用的屬性及其方法,更全的看MDN文檔: //developer.mozilla.org/en-US/docs/Web/API/notification

狀態值

permission:

只讀屬性,表示當前顯示通知許可權的字元串,為以下值:

  • denied: 拒絕顯示通知
  • granted: 接受顯示通知
  • default: 未選擇,瀏覽器默認將其當作拒絕的行為
Notification.permission

授權

requestPermission:

向用戶請求顯示通知的許可權。只有當 permission 的值為 default 時調用此方法,右上角才會顯示授權彈窗。如果用戶此前已選擇過,那麼再次調用直接返回狀態值。

Notification.requestPermission().then(res => {
  // denied 或 granted
  console.log(res) 
})

需要注意的是,用戶如果選擇拒絕後,再次調用也不會彈出授權提示。想要再次更改狀態,只能由用戶手動設置:

  • 第一種:點擊地址欄前的小按鈕(感嘆號或小鎖),設置通知狀態
  • 第二種:chrome 瀏覽器右上角 設置 >> 隱私設置和安全性 >> 網站設置 >> 通知

構造實例

new Notification(title[,options])

當用戶允許授權後,構造實例後,瀏覽器就會彈窗提示。

let notification = new Notification('通知標題', {
  // 正文內容
  body: '已經錯過的風景就不要再打聽了,當你選定了一個方向,另一邊的風景便與你無關了。',
  // 圖標
  icon: '//common.cnblogs.com/images/wechat.png',
  // 預覽大圖
  image: '//user-gold-cdn.xitu.io/2020/5/18/1722800bd522f520?imageView2/1/w/1304/h/734/q/85/format/webp/interlace/1',
  // 通知id
  tag: 1,
  // 是否一直保持有效
  requireInteraction: true
})

tag:

通知的ID,默認 tag 為空。當 tag 相同時,重複構造實例,新通知會替換舊通知。反之,通知不會替換,而是像樓層一樣疊加。同樣的,忽略 tag 屬性,通知也不會替換。

requireInteraction:

通知是否保持,不會自動關閉。默認為 false,會自動關閉。當設置為 true 時,由用戶手動關閉或調用實例的 close 方法進行關閉。

notification.close()

事件處理

監聽用戶點擊通知時,可以為實例添加事件:

let notification = new Notification('通知標題', {
  body'已經錯過的風景就不要再打聽了,當你選定了一個方向,另一邊的風景便與你無關了。',
  icon'//common.cnblogs.com/images/wechat.png',
  image'//user-gold-cdn.xitu.io/2020/5/18/1722800bd522f520?imageView2/1/w/1304/h/734/q/85/format/webp/interlace/1',
  tag1
})

notification.onclick = function ({
  alert('用戶點擊了通知')
}

如果想要在事件內獲取一些自定義參數資訊,可以為實例添加 data 屬性:

let notification = new Notification('通知標題', {
  body'已經錯過的風景就不要再打聽了,當你選定了一個方向,另一邊的風景便與你無關了。',
  icon'//common.cnblogs.com/images/wechat.png',
  image'//user-gold-cdn.xitu.io/2020/5/18/1722800bd522f520?imageView2/1/w/1304/h/734/q/85/format/webp/interlace/1',
  tag1,
  data: {
    url'//juejin.im'
  }
})

notification.onclick = function (e{
  window.open(e.target.data.url, '_blank')
}

實例上還可以綁定事件 show(顯示通知時觸發) 、close(關閉通知時觸發)、error(通知錯誤時觸發)。

MDN 文檔上提示,onshowonclose 是一個過時的API,不保證可以正常工作。但在 chrome 瀏覽器測試使用這兩個 API,還是能夠工作的,最好還是慎用吧。

封裝Notification

為了方便調用,簡單封裝創建 Notification 的方法,在原基礎上加入消息時長配置

/*
* @param {string} title - 消息標題
* @param {object} options - 消息配置
* @param {number} duration - 消息時長
* @param {function} onclick
* @param {function} onshow
* @param {function} onclose
* @param {function} onerror
* @return {object}
*/

async function createNotify(data{
  // 一些判斷
  if (window.Notification) {
    if (Notification.permission === 'granted') {
      return notify(data)
    } else if (Notification.permission === 'default') {
      let [err, status] = await Notification.requestPermission().then(status => [null, status]).catch(err => [err, null])
      return err || status === 'denied' ? Promise.reject() : notify(data)
    }
  }
  // 構造實例
  function notify(data{
    let { title, options, duration } = data
    options.requireInteraction = true
    let notification = new Notification(title, options)
    setTimeout(()=> notification.close(), duration || 5000)
    // 綁定事件
    let methods = ['onclick''onshow''onclose''onerror']
    for(let i = 0; i < methods.length; i++) {
      let method = methods[i]
      if (typeof options[method] === 'function') {
        notification[method] = options[method]
      }
    }
    return notification
  }
  return Promise.reject()
}

使用

createNotify({
  title'標題',
  options: {
    body'消息內容'
  },
  duration3000
})

瀏覽器支援

PC 端支援還不錯,移動端就基本一片紅了…

兼容性查詢://www.caniuse.com/#search=Notification

Tags: