使用js原生的API:Notification
封装了处理系统通知的方法,包括请求通知权限,创建通知,关闭单个通知,清楚所有通知
四个方法
请求通知权限
// 请求通知权限
export const requestNotificationPermission = () => {
return Notification.requestPermission().then((permission: string) => {
if (permission === 'granted') {
console.log('Notify allowed')
return true
} else if (permission === 'denied') {
console.log('Notify reject')
return false
}
})
}
创建通知
type optionsType = {
badge?: string; //一个 USVString 包含用于表示通知的图像的 URL,当没有足够的空间来显示通知本身时
body?: string; //一个 DOMString 表示通知的正文,将显示在标题下方。
dir?: NotificationDirection; //显示通知的方向。默认是 auto,跟随浏览器语言设置行为,你也可以通过设置 ltr 和 rtl 的值来覆盖该行为
icon?: string; //一个 USVString 包含要在通知中显示的图标的 URL。
lang?: string; //通知的语言
tag?: string; //一个 DOMString 代表通知的 一个识别标签。
image?: string; //一个 USVString包含要在通知中显示的图像的 URL。
data?: any; //您想要与通知相关联的任意数据。这可以是任何数据类型。
vibrate?: any; //一个振动模式 vibration pattern (en-US) 设备的振动硬件在通知触发时发出。
renotify?: boolean; //一个 Boolean (en-US) 指定在新通知替换旧通知后是否应通知用户。默认值为 false,这意味着它们不会被通知。
requireInteraction?: boolean; //表示通知应保持有效,直到用户点击或关闭它,而不是自动关闭。默认值为 false。
silent?: boolean; //个 Boolean (en-US) 指明通知是否应该是无声的,即,不需要发出声音或振动,无论设备设置如何。默认值为 false,这意味着它不会保持静默。
sound?: string; //一个 USVString 包含通知触发时要播放的音频文件的 URL。
noscreen?: boolean; //一个 Boolean (en-US) 指定通知触发是否应启用设备的屏幕。默认值为 false,这意味着它将启用屏幕。
sticky?: boolean; //一个 Boolean (en-US) 指明通知是否应该是“粘”, 即不易被用户清理。默认值为 false,这意味着它不会粘。
timeout?: number; //超时时间,默认5秒后关闭,若非常驻提示,最高设置5秒存在时间,单位ms
onClickCallback?: () => any; //点击通知之后的回调函数
}
let allNotification: any[] = []
// 创建通知
export const createNotification = (title: string, options: optionsType) => {
if (Notification.permission === 'granted') {
const { timeout, onClickCallback, requireInteraction } = options
options.silent = true
if (navigator.userAgent.indexOf('Firefox') != -1 && title.length > 30) {
// 用户使用的是 Firefox 浏览器,超过一行直接截断,若没这个需求可以不处理
title = title.slice(0, 50) + '...'
}
let notification = new Notification(title, options)
allNotification.push(notification)
if (!requireInteraction) {
setTimeout(() => {
notification.close()
}, timeout && timeout < 5000 ? timeout : 5000)
}
notification.onclick = function (e: any) {
if (onClickCallback && typeof onClickCallback === 'function') {
onClickCallback()
}
notification.close()
}
notification.onclose = function (e: any) {
const { timestamp } = e.currentTarget
const closeIndex = allNotification.findIndex((item: any) => {
return item.timestamp === timestamp
})
if (closeIndex >= 0) {
allNotification.splice(closeIndex, 1)
}
}
}
}
根据通知tag关闭单个通知
export const closeNotification = (tag: string) => {
const closeIndex = allNotification.findIndex((item: any) => {
return item.tag === tag
})
if (closeIndex >= 0) {
if (allNotification[closeIndex].close) {
allNotification[closeIndex].close()
allNotification.splice(closeIndex, 1)
}
}
}
清除所有通知
// 清除所有通知
export const clearNotification = () => {
allNotification.forEach((item: any) => {
if (item.close) item.close()
})
allNotification = []
}
完整代码
type optionsType = {
badge?: string; //一个 USVString 包含用于表示通知的图像的 URL,当没有足够的空间来显示通知本身时
body?: string; //一个 DOMString 表示通知的正文,将显示在标题下方。
dir?: NotificationDirection; //显示通知的方向。默认是 auto,跟随浏览器语言设置行为,你也可以通过设置 ltr 和 rtl 的值来覆盖该行为
icon?: string; //一个 USVString 包含要在通知中显示的图标的 URL。
lang?: string; //通知的语言
tag?: string; //一个 DOMString 代表通知的 一个识别标签。
image?: string; //一个 USVString包含要在通知中显示的图像的 URL。
data?: any; //您想要与通知相关联的任意数据。这可以是任何数据类型。
vibrate?: any; //一个振动模式 vibration pattern (en-US) 设备的振动硬件在通知触发时发出。
renotify?: boolean; //一个 Boolean (en-US) 指定在新通知替换旧通知后是否应通知用户。默认值为 false,这意味着它们不会被通知。
requireInteraction?: boolean; //表示通知应保持有效,直到用户点击或关闭它,而不是自动关闭。默认值为 false。
silent?: boolean; //个 Boolean (en-US) 指明通知是否应该是无声的,即,不需要发出声音或振动,无论设备设置如何。默认值为 false,这意味着它不会保持静默。
sound?: string; //一个 USVString 包含通知触发时要播放的音频文件的 URL。
noscreen?: boolean; //一个 Boolean (en-US) 指定通知触发是否应启用设备的屏幕。默认值为 false,这意味着它将启用屏幕。
sticky?: boolean; //一个 Boolean (en-US) 指明通知是否应该是“粘”, 即不易被用户清理。默认值为 false,这意味着它不会粘。
timeout?: number; //超时时间,默认5秒后关闭,若非常驻提示,最高设置5秒存在时间,单位ms
onClickCallback?: () => any; //点击通知之后的回调函数
}
let allNotification: any[] = []
// 创建通知
export const createNotification = (title: string, options: optionsType) => {
if (Notification.permission === 'granted') {
const { timeout, onClickCallback, requireInteraction } = options
options.silent = true
if (navigator.userAgent.indexOf('Firefox') != -1 && title.length > 30) {
// 用户使用的是 Firefox 浏览器
title = title.slice(0, 50) + '...'
}
let notification = new Notification(title, options)
allNotification.push(notification)
if (!requireInteraction) {
setTimeout(() => {
notification.close()
}, timeout && timeout < 5000 ? timeout : 5000)
}
notification.onclick = function (e: any) {
if (onClickCallback && typeof onClickCallback === 'function') {
onClickCallback()
}
notification.close()
}
notification.onclose = function (e: any) {
const { timestamp } = e.currentTarget
const closeIndex = allNotification.findIndex((item: any) => {
return item.timestamp === timestamp
})
if (closeIndex >= 0) {
allNotification.splice(closeIndex, 1)
}
}
}
}
// 根据通知tag关闭单个通知
export const closeNotification = (tag: string) => {
const closeIndex = allNotification.findIndex((item: any) => {
return item.tag === tag
})
if (closeIndex >= 0) {
if (allNotification[closeIndex].close) {
allNotification[closeIndex].close()
allNotification.splice(closeIndex, 1)
}
}
}
// 清除所有通知
export const clearNotification = () => {
allNotification.forEach((item: any) => {
if (item.close) item.close()
})
allNotification = []
}
// 请求通知权限
export const requestNotificationPermission = () => {
return Notification.requestPermission().then((permission: string) => {
if (permission === 'granted') {
console.log('Notify allowed')
return true
} else if (permission === 'denied') {
console.log('Notify reject')
return false
}
})
}
项目中使用(测试案例)
createNotification('123', {
icon: square, // 文件中导入的图标文件
body: '456',
onClickCallback: function () {
window.focus()
},
})