// 建议将这类工具函数放在单独的文件中,例如 src/utils/notification.js
export function notifyMe(title, options = {}) {
// 1. 环境检查:首先检查是否在浏览器环境中,避免在 SSR (Server-Side Rendering) 时出错
if (typeof window === 'undefined') {
console.warn('Notification is not available in a non-browser environment.');
return Promise.reject(new Error('非浏览器环境,不支持 Notification'));
}
// 2. 特性检测:检查浏览器是否支持 Notification API
if (!('Notification' in window)) {
console.warn('This browser does not support desktop notification.');
// 返回一个被拒绝的 Promise,让调用方可以优雅地处理
return Promise.reject(new Error('此浏览器不支持桌面通知'));
}
// 3. 权限处理与通知创建
// 如果权限已经被授予,直接创建通知
if (Notification.permission === 'granted') {
return createNotification(title, options);
}
// 如果权限尚未被设置(即 'default'),则请求权限
else if (Notification.permission !== 'denied') {
return Notification.requestPermission().then(permission => {
if (permission === 'granted') {
console.log('Notification permission granted.');
return createNotification(title, options);
} else {
// 如果用户拒绝或关闭了权限请求,打印警告并返回拒绝的 Promise
console.warn(`Notification permission ${permission}.`);
return Promise.reject(new Error(`通知权限被${permission === 'denied' ? '拒绝' : '忽略'}`));
}
});
}
// 4. 如果权限已被拒绝,直接返回拒绝的 Promise
else {
console.warn('Notification permission has been denied.');
return Promise.reject(new Error('通知权限已被拒绝,请在浏览器设置中更改'));
}
}
/**
* 内部辅助函数:创建并返回一个 Notification 实例
* @param {string} title - 通知的标题
* @param {object} options - 通知的选项,如 body, icon 等
* @returns {Promise<Notification>} - 返回一个 resolved 的 Promise,其值为 Notification 实例
*/
function createNotification(title, options) {
// 为通知添加默认图标(如果未提供),提升用户体验
const defaultOptions = {
icon: '/favicon.ico' // 假设你的项目根目录下有一个 favicon.ico
};
const notification = new Notification(title, { ...defaultOptions, ...options });
// 将 Notification 实例包装在 Promise 中返回,方便调用方监听其事件
return Promise.resolve(notification);
}
在vue页面使用
<template>
<div>
<button @click="requestNotification">请求并发送通知</button>
<button @click="sendNotification" :disabled="!hasPermission">发送通知</button>
</div>
</template>
<script>
import { notifyMe } from '@/utils/notification';
export default {
data() {
return {
hasPermission: Notification.permission === 'granted'
};
},
methods: {
requestNotification() {
notifyMe('你好,世界!', { body: '这是一条来自 Vue 的桌面通知。' })
.then(notification => {
console.log('通知已显示:', notification);
// 你可以在这里监听通知的点击事件
notification.onclick = () => {
console.log('用户点击了通知');
window.focus(); // 点击通知后聚焦到浏览器窗口
notification.close(); // 关闭通知
};
this.hasPermission = true;
})
.catch(error => {
console.error('发送通知失败:', error.message);
// 在这里可以向用户显示一个友好的错误提示,例如一个 Toast
alert(`通知失败: ${error.message}`);
});
},
sendNotification() {
if (Notification.permission !== 'granted') {
alert('请先授予通知权限');
return;
}
notifyMe('新消息', {
body: '你收到了一条新的系统消息。',
icon: '/path/to/your/icon.png', // 自定义图标
// 其他可用选项:tag, data, vibrate, sound, timestamp 等
});
}
}
}
</script>
1811

被折叠的 条评论
为什么被折叠?



