首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >浏览器原生API实战:Clipboard API、Notification API与更多实用API详解

浏览器原生API实战:Clipboard API、Notification API与更多实用API详解

作者头像
fruge365
发布2025-12-15 13:34:16
发布2025-12-15 13:34:16
1980
举报

浏览器原生API实战:Clipboard API、Notification API与更多实用API详解

前言

在现代前端开发中,浏览器原生API为我们提供了强大的功能,让我们能够在不依赖第三方库的情况下实现复杂的功能。本文将深入探讨几个实用的浏览器原生API,包括Clipboard API、Notification API等,通过实际案例帮助你掌握这些API的使用技巧。

1. Clipboard API - 剪贴板操作的艺术

1.1 基础概念

Clipboard API提供了对系统剪贴板的异步访问,让我们能够读取和写入文本、图片等各种数据类型。这个API在现代浏览器中得到了广泛支持,是实现复制粘贴功能的现代方案。

1.2 核心方法与属性
代码语言:javascript
复制
// 基础文本操作
navigator.clipboard.writeText('要复制的文本')
  .then(() => console.log('文本已复制到剪贴板'))
  .catch(err => console.error('复制失败:', err));

// 读取剪贴板文本
navigator.clipboard.readText()
  .then(text => console.log('剪贴板内容:', text))
  .catch(err => console.error('读取失败:', err));
1.3 实战案例:智能复制按钮
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能复制功能</title>
    <style>
        .copy-container {
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        .copy-item {
            display: flex;
            align-items: center;
            margin: 15px 0;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 8px;
            border-left: 4px solid #007bff;
        }
        
        .copy-text {
            flex: 1;
            margin-right: 15px;
            font-size: 14px;
            color: #333;
        }
        
        .copy-btn {
            padding: 8px 16px;
            background: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s ease;
        }
        
        .copy-btn:hover {
            background: #0056b3;
            transform: translateY(-1px);
        }
        
        .copy-btn.copied {
            background: #28a745;
        }
        
        .status-message {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 12px 20px;
            background: #28a745;
            color: white;
            border-radius: 4px;
            opacity: 0;
            transform: translateY(-20px);
            transition: all 0.3s ease;
            z-index: 1000;
        }
        
        .status-message.show {
            opacity: 1;
            transform: translateY(0);
        }
    </style>
</head>
<body>
    <div class="copy-container">
        <h1>智能复制功能演示</h1>
        <p>点击下方按钮复制不同的内容到剪贴板</p>
        
        <div class="copy-item">
            <div class="copy-text">https://github.com/awesome-project</div>
            <button class="copy-btn" onclick="copyText(this, 'https://github.com/awesome-project')">复制链接</button>
        </div>
        
        <div class="copy-item">
            <div class="copy-text">const message = 'Hello, World!';</div>
            <button class="copy-btn" onclick="copyText(this, \"const message = 'Hello, World!';\")">复制代码</button>
        </div>
        
        <div class="copy-item">
            <div class="copy-text">contact@example.com</div>
            <button class="copy-btn" onclick="copyText(this, 'contact@example.com')">复制邮箱</button>
        </div>
    </div>
    
    <div id="statusMessage" class="status-message"></div>

    <script>
        async function copyText(button, text) {
            try {
                // 使用现代的 Clipboard API
                await navigator.clipboard.writeText(text);
                
                // 视觉反馈
                button.classList.add('copied');
                button.textContent = '已复制!';
                
                // 显示状态消息
                showStatusMessage('内容已复制到剪贴板');
                
                // 3秒后恢复按钮状态
                setTimeout(() => {
                    button.classList.remove('copied');
                    button.textContent = button.getAttribute('data-original-text') || '复制';
                }, 3000);
                
            } catch (err) {
                console.error('复制失败:', err);
                showStatusMessage('复制失败,请重试', 'error');
                
                // 降级方案:使用传统的复制方法
                fallbackCopyText(text);
            }
        }
        
        function showStatusMessage(message, type = 'success') {
            const statusEl = document.getElementById('statusMessage');
            statusEl.textContent = message;
            statusEl.style.background = type === 'error' ? '#dc3545' : '#28a745';
            statusEl.classList.add('show');
            
            setTimeout(() => {
                statusEl.classList.remove('show');
            }, 3000);
        }
        
        // 降级复制方案
        function fallbackCopyText(text) {
            const textArea = document.createElement('textarea');
            textArea.value = text;
            textArea.style.position = 'fixed';
            textArea.style.left = '-999999px';
            textArea.style.top = '-999999px';
            document.body.appendChild(textArea);
            textArea.focus();
            textArea.select();
            
            try {
                document.execCommand('copy');
                showStatusMessage('内容已复制到剪贴板');
            } catch (err) {
                showStatusMessage('复制失败,请手动复制', 'error');
            }
            
            document.body.removeChild(textArea);
        }
        
        // 为按钮保存原始文本
        document.querySelectorAll('.copy-btn').forEach(btn => {
            btn.setAttribute('data-original-text', btn.textContent);
        });
    </script>
</body>
</html>
1.4 高级用法:复制富文本和HTML
代码语言:javascript
复制
// 复制HTML内容
async function copyHTML() {
    const htmlContent = `
        <div style="color: blue; font-weight: bold;">
            这是复制的HTML内容
        </div>
    `;
    
    try {
        // 创建Blob对象
        const blob = new Blob([htmlContent], { type: 'text/html' });
        
        // 创建ClipboardItem
        const clipboardItem = new ClipboardItem({
            'text/html': blob,
            'text/plain': new Blob(['纯文本内容'], { type: 'text/plain' })
        });
        
        await navigator.clipboard.write([clipboardItem]);
        console.log('富文本已复制');
    } catch (err) {
        console.error('复制富文本失败:', err);
    }
}
1.5 权限管理
代码语言:javascript
复制
// 检查剪贴板权限
async function checkClipboardPermission() {
    try {
        const result = await navigator.permissions.query({ name: 'clipboard-read' });
        console.log('剪贴板读取权限:', result.state); // granted, denied, prompt
        
        if (result.state === 'granted') {
            // 有权限,可以直接读取
            const text = await navigator.clipboard.readText();
            console.log('剪贴板内容:', text);
        } else if (result.state === 'prompt') {
            // 需要用户授权
            console.log('需要用户授权剪贴板访问');
        }
    } catch (err) {
        console.error('权限检查失败:', err);
    }
}

2. Notification API - 桌面通知系统

2.1 基础概念

Notification API允许网页向用户显示系统通知,即使用户没有打开你的网站。这是提升用户体验和增加用户参与度的强大工具。

2.2 权限请求与基础使用
代码语言:javascript
复制
// 请求通知权限
async function requestNotificationPermission() {
    if (!('Notification' in window)) {
        console.log('此浏览器不支持通知');
        return;
    }
    
    const permission = await Notification.requestPermission();
    console.log('通知权限:', permission); // granted, denied, default
    
    return permission;
}

// 发送简单通知
function sendBasicNotification() {
    if (Notification.permission === 'granted') {
        new Notification('你好!', {
            body: '这是一条测试通知',
            icon: '/path/to/icon.png'
        });
    }
}
2.3 实战案例:智能通知系统
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>智能通知系统</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .notification-container {
            background: white;
            padding: 40px;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0,0,0,0.1);
            max-width: 500px;
            width: 90%;
        }
        
        h1 {
            text-align: center;
            color: #333;
            margin-bottom: 30px;
            font-size: 28px;
        }
        
        .permission-section {
            margin-bottom: 30px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 10px;
            text-align: center;
        }
        
        .permission-status {
            display: inline-block;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 14px;
            font-weight: bold;
            margin-top: 10px;
        }
        
        .permission-status.granted {
            background: #d4edda;
            color: #155724;
        }
        
        .permission-status.denied {
            background: #f8d7da;
            color: #721c24;
        }
        
        .permission-status.default {
            background: #fff3cd;
            color: #856404;
        }
        
        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin: 10px 5px;
            font-weight: 500;
        }
        
        .btn-primary {
            background: #007bff;
            color: white;
        }
        
        .btn-success {
            background: #28a745;
            color: white;
        }
        
        .btn-warning {
            background: #ffc107;
            color: #212529;
        }
        
        .btn-info {
            background: #17a2b8;
            color: white;
        }
        
        .btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
        }
        
        .notification-form {
            margin-top: 30px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 5px;
            color: #555;
            font-weight: 500;
        }
        
        input, textarea, select {
            width: 100%;
            padding: 12px;
            border: 2px solid #e9ecef;
            border-radius: 8px;
            font-size: 14px;
            transition: border-color 0.3s ease;
        }
        
        input:focus, textarea:focus, select:focus {
            outline: none;
            border-color: #007bff;
        }
        
        .notification-log {
            margin-top: 30px;
            max-height: 200px;
            overflow-y: auto;
            background: #f8f9fa;
            padding: 15px;
            border-radius: 8px;
        }
        
        .log-item {
            padding: 8px 12px;
            margin: 5px 0;
            background: white;
            border-radius: 4px;
            border-left: 4px solid #007bff;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="notification-container">
        <h1>🚀 智能通知系统</h1>
        
        <div class="permission-section">
            <h3>通知权限状态</h3>
            <div id="permissionStatus" class="permission-status default">未检查</div>
            <button class="btn btn-primary" onclick="checkPermission()">检查权限</button>
            <button class="btn btn-warning" onclick="requestPermission()">请求权限</button>
        </div>
        
        <div class="notification-form">
            <h3>发送自定义通知</h3>
            <div class="form-group">
                <label for="notificationTitle">通知标题:</label>
                <input type="text" id="notificationTitle" value="测试通知" placeholder="输入通知标题">
            </div>
            
            <div class="form-group">
                <label for="notificationBody">通知内容:</label>
                <textarea id="notificationBody" rows="3" placeholder="输入通知内容">这是一条测试通知消息</textarea>
            </div>
            
            <div class="form-group">
                <label for="notificationIcon">图标URL (可选):</label>
                <input type="url" id="notificationIcon" placeholder="https://example.com/icon.png">
            </div>
            
            <div class="form-group">
                <label for="notificationTag">标签 (可选):</label>
                <input type="text" id="notificationTag" placeholder="通知标签,用于替换相同标签的通知">
            </div>
            
            <div class="form-group">
                <label for="notificationTimeout">自动关闭时间 (秒):</label>
                <select id="notificationTimeout">
                    <option value="0">不自动关闭</option>
                    <option value="3">3秒</option>
                    <option value="5" selected>5秒</option>
                    <option value="10">10秒</option>
                </select>
            </div>
            
            <button class="btn btn-success" onclick="sendCustomNotification()">发送通知</button>
            <button class="btn btn-info" onclick="sendAdvancedNotification()">发送高级通知</button>
        </div>
        
        <div class="notification-log">
            <h3>通知日志</h3>
            <div id="notificationLog"></div>
        </div>
    </div>

    <script>
        let notificationCounter = 0;
        
        // 检查当前权限状态
        function checkPermission() {
            if (!('Notification' in window)) {
                updatePermissionStatus('unsupported');
                return;
            }
            
            updatePermissionStatus(Notification.permission);
        }
        
        // 更新权限状态显示
        function updatePermissionStatus(status) {
            const statusEl = document.getElementById('permissionStatus');
            statusEl.className = `permission-status ${status}`;
            
            switch(status) {
                case 'granted':
                    statusEl.textContent = '✅ 已授权';
                    break;
                case 'denied':
                    statusEl.textContent = '❌ 已拒绝';
                    break;
                case 'default':
                    statusEl.textContent = '⏳ 默认状态';
                    break;
                case 'unsupported':
                    statusEl.textContent = '⚠️ 浏览器不支持';
                    break;
            }
        }
        
        // 请求通知权限
        async function requestPermission() {
            if (!('Notification' in window)) {
                addLog('浏览器不支持通知功能');
                return;
            }
            
            try {
                const permission = await Notification.requestPermission();
                updatePermissionStatus(permission);
                addLog(`权限请求结果: ${permission}`);
            } catch (error) {
                addLog(`权限请求失败: ${error.message}`);
            }
        }
        
        // 发送自定义通知
        function sendCustomNotification() {
            if (Notification.permission !== 'granted') {
                addLog('没有通知权限,请先请求权限');
                return;
            }
            
            const title = document.getElementById('notificationTitle').value || '默认标题';
            const body = document.getElementById('notificationBody').value || '默认内容';
            const icon = document.getElementById('notificationIcon').value;
            const tag = document.getElementById('notificationTag').value;
            const timeout = parseInt(document.getElementById('notificationTimeout').value);
            
            const options = {
                body: body,
                icon: icon || undefined,
                tag: tag || undefined,
                timestamp: Date.now()
            };
            
            try {
                const notification = new Notification(title, options);
                notificationCounter++;
                
                notification.onclick = function() {
                    addLog(`通知 #${notificationCounter} 被点击`);
                    window.focus();
                    notification.close();
                };
                
                notification.onshow = function() {
                    addLog(`通知 #${notificationCounter} 已显示`);
                };
                
                notification.onclose = function() {
                    addLog(`通知 #${notificationCounter} 已关闭`);
                };
                
                notification.onerror = function() {
                    addLog(`通知 #${notificationCounter} 显示失败`);
                };
                
                // 自动关闭
                if (timeout > 0) {
                    setTimeout(() => {
                        notification.close();
                    }, timeout * 1000);
                }
                
                addLog(`通知 #${notificationCounter} 发送成功`);
                
            } catch (error) {
                addLog(`通知发送失败: ${error.message}`);
            }
        }
        
        // 发送高级通知(使用Service Worker)
        async function sendAdvancedNotification() {
            if (Notification.permission !== 'granted') {
                addLog('没有通知权限,请先请求权限');
                return;
            }
            
            // 检查是否支持Service Worker
            if (!('serviceWorker' in navigator)) {
                addLog('浏览器不支持Service Worker,使用基础通知');
                sendCustomNotification();
                return;
            }
            
            try {
                const registration = await navigator.serviceWorker.register('data:text/javascript,' + encodeURIComponent(`
                    self.addEventListener('notificationclick', function(event) {
                        event.notification.close();
                        event.waitUntil(
                            clients.openWindow('https://example.com')
                        );
                    });
                `));
                
                const title = document.getElementById('notificationTitle').value || '高级通知';
                const options = {
                    body: '这是通过Service Worker发送的高级通知',
                    icon: '/favicon.ico',
                    badge: '/favicon.ico',
                    vibrate: [200, 100, 200],
                    actions: [
                        { action: 'view', title: '查看详情' },
                        { action: 'close', title: '关闭' }
                    ],
                    data: {
                        url: 'https://example.com',
                        timestamp: Date.now()
                    }
                };
                
                await registration.showNotification(title, options);
                addLog('高级通知发送成功');
                
            } catch (error) {
                addLog(`高级通知发送失败: ${error.message}`);
                // 降级到基础通知
                sendCustomNotification();
            }
        }
        
        // 添加日志
        function addLog(message) {
            const logEl = document.getElementById('notificationLog');
            const logItem = document.createElement('div');
            logItem.className = 'log-item';
            const time = new Date().toLocaleTimeString();
            logItem.textContent = `[${time}] ${message}`;
            
            logEl.insertBefore(logItem, logEl.firstChild);
            
            // 限制日志数量
            while (logEl.children.length > 20) {
                logEl.removeChild(logEl.lastChild);
            }
        }
        
        // 页面加载时检查权限
        window.onload = function() {
            checkPermission();
            addLog('页面加载完成');
        };
    </script>
</body>
</html>
2.4 通知最佳实践
代码语言:javascript
复制
// 通知管理器类
class NotificationManager {
    constructor() {
        this.notifications = new Map();
        this.maxNotifications = 5;
    }
    
    async send(options) {
        if (Notification.permission !== 'granted') {
            throw new Error('没有通知权限');
        }
        
        // 限制通知数量
        if (this.notifications.size >= this.maxNotifications) {
            const oldestKey = this.notifications.keys().next().value;
            this.notifications.get(oldestKey).close();
            this.notifications.delete(oldestKey);
        }
        
        const notification = new Notification(options.title, {
            body: options.body,
            icon: options.icon,
            tag: options.tag || Date.now().toString(),
            requireInteraction: options.requireInteraction || false
        });
        
        const id = options.tag || Date.now().toString();
        this.notifications.set(id, notification);
        
        // 监听事件
        notification.onclick = () => {
            options.onClick?.();
            this.close(id);
        };
        
        notification.onclose = () => {
            this.notifications.delete(id);
            options.onClose?.();
        };
        
        // 自动关闭
        if (options.autoClose) {
            setTimeout(() => this.close(id), options.autoClose);
        }
        
        return id;
    }
    
    close(id) {
        const notification = this.notifications.get(id);
        if (notification) {
            notification.close();
            this.notifications.delete(id);
        }
    }
    
    closeAll() {
        this.notifications.forEach(notification => notification.close());
        this.notifications.clear();
    }
}

// 使用示例
const notificationManager = new NotificationManager();

// 发送重要通知
notificationManager.send({
    title: '重要提醒',
    body: '您有一个重要会议即将开始',
    icon: '/important-icon.png',
    requireInteraction: true,
    autoClose: 10000,
    onClick: () => {
        window.focus();
        // 打开相关页面
    }
});

3. 其他实用浏览器原生API

3.1 Geolocation API - 地理位置获取
代码语言:javascript
复制
// 获取用户位置
function getUserLocation() {
    if (!navigator.geolocation) {
        console.log('浏览器不支持地理定位');
        return;
    }
    
    const options = {
        enableHighAccuracy: true, // 高精度
        timeout: 5000, // 5秒超时
        maximumAge: 0 // 不使用缓存
    };
    
    navigator.geolocation.getCurrentPosition(
        (position) => {
            console.log('纬度:', position.coords.latitude);
            console.log('经度:', position.coords.longitude);
            console.log('精度:', position.coords.accuracy);
            console.log('海拔:', position.coords.altitude);
            console.log('速度:', position.coords.speed);
        },
        (error) => {
            console.error('获取位置失败:', error.message);
            switch(error.code) {
                case error.PERMISSION_DENIED:
                    console.log('用户拒绝了地理定位请求');
                    break;
                case error.POSITION_UNAVAILABLE:
                    console.log('位置信息不可用');
                    break;
                case error.TIMEOUT:
                    console.log('获取位置超时');
                    break;
            }
        },
        options
    );
}

// 持续监听位置变化
const watchId = navigator.geolocation.watchPosition(
    (position) => {
        console.log('位置更新:', position.coords.latitude, position.coords.longitude);
    },
    (error) => {
        console.error('位置监听错误:', error);
    }
);

// 停止监听
navigator.geolocation.clearWatch(watchId);
3.2 Battery API - 电池状态监控
代码语言:javascript
复制
// 获取电池信息(部分浏览器支持)
async function getBatteryInfo() {
    if (!navigator.getBattery) {
        console.log('浏览器不支持电池API');
        return;
    }
    
    try {
        const battery = await navigator.getBattery();
        
        console.log('电池电量:', battery.level * 100 + '%');
        console.log('是否充电:', battery.charging);
        console.log('充电时间:', battery.chargingTime + '秒');
        console.log('剩余时间:', battery.dischargingTime + '秒');
        
        // 监听电池状态变化
        battery.addEventListener('levelchange', () => {
            console.log('电量变化:', battery.level * 100 + '%');
        });
        
        battery.addEventListener('chargingchange', () => {
            console.log('充电状态变化:', battery.charging);
        });
        
        battery.addEventListener('chargingtimechange', () => {
            console.log('充电时间变化:', battery.chargingTime);
        });
        
        battery.addEventListener('dischargingtimechange', () => {
            console.log('剩余时间变化:', battery.dischargingTime);
        });
        
    } catch (error) {
        console.error('获取电池信息失败:', error);
    }
}
3.3 Network Information API - 网络状态检测
代码语言:javascript
复制
// 获取网络信息
function getNetworkInfo() {
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
    
    if (!connection) {
        console.log('浏览器不支持网络信息API');
        return;
    }
    
    console.log('网络类型:', connection.type); // bluetooth, cellular, ethernet, wifi, wimax, other, none
    console.log('有效网络类型:', connection.effectiveType); // slow-2g, 2g, 3g, 4g
    console.log('下行速度:', connection.downlink + 'Mb/s');
    console.log('往返时间:', connection.rtt + 'ms');
    console.log('节省数据模式:', connection.saveData);
    
    // 监听网络变化
    connection.addEventListener('change', () => {
        console.log('网络状态变化');
        console.log('新的网络类型:', connection.type);
        console.log('新的有效类型:', connection.effectiveType);
    });
}

// 根据网络状态调整应用行为
function adaptToNetworkConditions() {
    const connection = navigator.connection;
    
    if (connection) {
        if (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g') {
            // 慢速网络,降低图片质量,禁用自动播放
            console.log('检测到慢速网络,启用省流模式');
            enableDataSavingMode();
        } else if (connection.saveData) {
            // 用户启用了节省数据模式
            console.log('用户启用节省数据模式');
            enableDataSavingMode();
        }
    }
}

function enableDataSavingMode() {
    // 禁用自动播放视频
    // 使用低质量图片
    // 延迟加载非关键资源
    console.log('已启用省流模式');
}
3.4 Page Visibility API - 页面可见性检测
代码语言:javascript
复制
// 检测页面可见性变化
document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
        console.log('页面隐藏,暂停非必要操作');
        // 暂停视频播放
        // 停止轮询
        // 减少网络请求
    } else {
        console.log('页面可见,恢复正常操作');
        // 恢复视频播放
        // 重新开始轮询
        // 恢复网络请求
    }
});

// 实际应用示例
class PageVisibilityManager {
    constructor() {
        this.isVisible = !document.hidden;
        this.listeners = new Map();
        
        document.addEventListener('visibilitychange', () => {
            this.isVisible = !document.hidden;
            this.notifyListeners();
        });
    }
    
    onVisibilityChange(callback) {
        const id = Date.now().toString();
        this.listeners.set(id, callback);
        return id;
    }
    
    removeListener(id) {
        this.listeners.delete(id);
    }
    
    notifyListeners() {
        this.listeners.forEach(callback => {
            callback(this.isVisible);
        });
    }
    
    // 在页面可见时执行操作
    whenVisible(callback) {
        if (this.isVisible) {
            callback();
        } else {
            const id = this.onVisibilityChange((visible) => {
                if (visible) {
                    callback();
                    this.removeListener(id);
                }
            });
        }
    }
}

// 使用示例
const visibilityManager = new PageVisibilityManager();

// 监听可见性变化
visibilityManager.onVisibilityChange((isVisible) => {
    console.log('页面可见性:', isVisible);
});

// 只在页面可见时获取新数据
visibilityManager.whenVisible(() => {
    console.log('页面可见,获取最新数据');
    fetchLatestData();
});

function fetchLatestData() {
    console.log('获取最新数据...');
}
3.5 Fullscreen API - 全屏模式控制
代码语言:javascript
复制
// 进入全屏模式
async function enterFullscreen(element = document.documentElement) {
    try {
        if (element.requestFullscreen) {
            await element.requestFullscreen();
        } else if (element.webkitRequestFullscreen) {
            await element.webkitRequestFullscreen();
        } else if (element.msRequestFullscreen) {
            await element.msRequestFullscreen();
        }
        console.log('已进入全屏模式');
    } catch (error) {
        console.error('进入全屏失败:', error);
    }
}

// 退出全屏模式
async function exitFullscreen() {
    try {
        if (document.exitFullscreen) {
            await document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
            await document.webkitExitFullscreen();
        } else if (document.msExitFullscreen) {
            await document.msExitFullscreen();
        }
        console.log('已退出全屏模式');
    } catch (error) {
        console.error('退出全屏失败:', error);
    }
}

// 检测全屏状态变化
document.addEventListener('fullscreenchange', () => {
    if (document.fullscreenElement) {
        console.log('当前处于全屏模式');
    } else {
        console.log('当前处于窗口模式');
    }
});

// 全屏API实用类
class FullscreenManager {
    constructor() {
        this.isFullscreen = this.checkFullscreen();
        this.originalElement = null;
        
        document.addEventListener('fullscreenchange', () => {
            this.isFullscreen = this.checkFullscreen();
        });
    }
    
    checkFullscreen() {
        return !!(document.fullscreenElement || 
                  document.webkitFullscreenElement || 
                  document.msFullscreenElement);
    }
    
    async enter(element = document.documentElement) {
        this.originalElement = element;
        
        try {
            const requestMethod = element.requestFullscreen ||
                                element.webkitRequestFullscreen ||
                                element.msRequestFullscreen;
            
            if (requestMethod) {
                await requestMethod.call(element);
                return true;
            }
        } catch (error) {
            console.error('进入全屏失败:', error);
        }
        
        return false;
    }
    
    async exit() {
        try {
            const exitMethod = document.exitFullscreen ||
                             document.webkitExitFullscreen ||
                             document.msExitFullscreen;
            
            if (exitMethod) {
                await exitMethod.call(document);
                return true;
            }
        } catch (error) {
            console.error('退出全屏失败:', error);
        }
        
        return false;
    }
    
    toggle(element = document.documentElement) {
        if (this.isFullscreen) {
            return this.exit();
        } else {
            return this.enter(element);
        }
    }
    
    // 全屏时锁定方向(移动端)
    async lockOrientation(orientation) {
        if (screen.orientation && screen.orientation.lock) {
            try {
                await screen.orientation.lock(orientation);
                console.log('屏幕方向已锁定:', orientation);
            } catch (error) {
                console.error('锁定屏幕方向失败:', error);
            }
        }
    }
    
    // 解锁屏幕方向
    unlockOrientation() {
        if (screen.orientation && screen.orientation.unlock) {
            screen.orientation.unlock();
            console.log('屏幕方向已解锁');
        }
    }
}

// 使用示例
const fullscreenManager = new FullscreenManager();

// 全屏切换
document.getElementById('fullscreenBtn')?.addEventListener('click', () => {
    fullscreenManager.toggle();
});

// 全屏观看视频
function fullscreenVideo(videoElement) {
    fullscreenManager.enter(videoElement).then(success => {
        if (success && screen.orientation) {
            // 横屏显示(移动端)
            fullscreenManager.lockOrientation('landscape');
        }
    });
}

4. 浏览器兼容性处理

4.1 特性检测与降级方案
代码语言:javascript
复制
// 通用特性检测函数
function checkFeatureSupport(feature) {
    const features = {
        clipboard: () => 'clipboard' in navigator,
        notification: () => 'Notification' in window,
        geolocation: () => 'geolocation' in navigator,
        battery: () => 'getBattery' in navigator,
        networkInfo: () => 'connection' in navigator,
        pageVisibility: () => 'hidden' in document,
        fullscreen: () => 'requestFullscreen' in document.documentElement ||
                       'webkitRequestFullscreen' in document.documentElement ||
                       'msRequestFullscreen' in document.documentElement
    };
    
    return features[feature] ? features[feature]() : false;
}

// 兼容性管理器
class CompatibilityManager {
    constructor() {
        this.supportedFeatures = this.detectFeatures();
        this.polyfills = new Map();
    }
    
    detectFeatures() {
        return {
            clipboard: checkFeatureSupport('clipboard'),
            notification: checkFeatureSupport('notification'),
            geolocation: checkFeatureSupport('geolocation'),
            battery: checkFeatureSupport('battery'),
            networkInfo: checkFeatureSupport('networkInfo'),
            pageVisibility: checkFeatureSupport('pageVisibility'),
            fullscreen: checkFeatureSupport('fullscreen')
        };
    }
    
    // 检查是否支持某个特性
    isSupported(feature) {
        return this.supportedFeatures[feature] || false;
    }
    
    // 获取支持的特性列表
    getSupportedFeatures() {
        return Object.keys(this.supportedFeatures)
                   .filter(feature => this.supportedFeatures[feature]);
    }
    
    // 注册降级方案
    registerFallback(feature, fallbackFunction) {
        this.polyfills.set(feature, fallbackFunction);
    }
    
    // 执行带降级的操作
    async executeWithFallback(feature, primaryFunction, ...args) {
        if (this.isSupported(feature)) {
            try {
                return await primaryFunction(...args);
            } catch (error) {
                console.warn(`${feature} API 执行失败:`, error);
                
                const fallback = this.polyfills.get(feature);
                if (fallback) {
                    console.log(`使用 ${feature} 的降级方案`);
                    return await fallback(...args);
                }
                
                throw error;
            }
        } else {
            const fallback = this.polyfills.get(feature);
            if (fallback) {
                console.log(`浏览器不支持 ${feature},使用降级方案`);
                return await fallback(...args);
            }
            
            throw new Error(`浏览器不支持 ${feature},且无可用降级方案`);
        }
    }
}

// 创建兼容性管理器实例
const compatManager = new CompatibilityManager();

// 注册降级方案
compatManager.registerFallback('clipboard', {
    writeText: async (text) => {
        // 降级到传统的复制方法
        const textArea = document.createElement('textarea');
        textArea.value = text;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        
        try {
            document.execCommand('copy');
            return Promise.resolve();
        } catch (error) {
            return Promise.reject(error);
        } finally {
            document.body.removeChild(textArea);
        }
    }
});

// 使用示例
async function safeCopyText(text) {
    try {
        await compatManager.executeWithFallback(
            'clipboard',
            () => navigator.clipboard.writeText(text),
            text
        );
        console.log('复制成功');
    } catch (error) {
        console.error('复制失败:', error);
    }
}
4.2 浏览器版本检测
代码语言:javascript
复制
// 浏览器信息检测
class BrowserDetector {
    constructor() {
        this.ua = navigator.userAgent;
        this.browser = this.detectBrowser();
        this.version = this.detectVersion();
    }
    
    detectBrowser() {
        if (this.ua.includes('Chrome') && !this.ua.includes('Edg')) return 'Chrome';
        if (this.ua.includes('Safari') && !this.ua.includes('Chrome')) return 'Safari';
        if (this.ua.includes('Firefox')) return 'Firefox';
        if (this.ua.includes('Edg')) return 'Edge';
        if (this.ua.includes('Trident') || this.ua.includes('MSIE')) return 'IE';
        return 'Unknown';
    }
    
    detectVersion() {
        const regex = new RegExp(`${this.browser}\\/([\\d.]+)`);
        const match = this.ua.match(regex);
        return match ? match[1] : 'Unknown';
    }
    
    // 检查是否支持特定API版本
    supportsAPI(apiName, minVersion = null) {
        const supportMap = {
            'Chrome': {
                clipboard: '63',
                notification: '22',
                geolocation: '5',
                battery: '38',
                networkInfo: '61',
                pageVisibility: '33',
                fullscreen: '71'
            },
            'Firefox': {
                clipboard: '63',
                notification: '22',
                geolocation: '3.5',
                battery: '43',
                networkInfo: '62',
                pageVisibility: '18',
                fullscreen: '64'
            },
            'Safari': {
                clipboard: '13.1',
                notification: '7',
                geolocation: '5',
                battery: null, // 不支持
                networkInfo: '11.1',
                pageVisibility: '7',
                fullscreen: '12'
            },
            'Edge': {
                clipboard: '79',
                notification: '14',
                geolocation: '12',
                battery: '79',
                networkInfo: '79',
                pageVisibility: '12',
                fullscreen: '79'
            }
        };
        
        const browserSupport = supportMap[this.browser];
        if (!browserSupport || !browserSupport[apiName]) {
            return false;
        }
        
        if (!minVersion) {
            return true;
        }
        
        const supportedVersion = browserSupport[apiName];
        const currentVersion = this.version;
        
        return this.compareVersions(currentVersion, supportedVersion) >= 0;
    }
    
    compareVersions(v1, v2) {
        const parts1 = v1.split('.').map(Number);
        const parts2 = v2.split('.').map(Number);
        
        for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
            const part1 = parts1[i] || 0;
            const part2 = parts2[i] || 0;
            
            if (part1 > part2) return 1;
            if (part1 < part2) return -1;
        }
        
        return 0;
    }
}

// 使用示例
const browserDetector = new BrowserDetector();
console.log(`浏览器: ${browserDetector.browser} ${browserDetector.version}`);

// 检查特定API支持
if (browserDetector.supportsAPI('clipboard', '63')) {
    console.log('支持Clipboard API');
} else {
    console.log('不支持Clipboard API或版本过低');
}

5. 性能优化与安全考虑

5.1 性能优化策略
代码语言:javascript
复制
// API调用优化器
class APIOptimizer {
    constructor() {
        this.cache = new Map();
        this.pendingRequests = new Map();
        this.rateLimits = new Map();
    }
    
    // 带缓存的API调用
    async cachedAPICall(key, apiFunction, ttl = 60000) {
        const cached = this.cache.get(key);
        
        if (cached && Date.now() - cached.timestamp < ttl) {
            console.log(`使用缓存的数据: ${key}`);
            return cached.data;
        }
        
        // 检查是否有正在进行的请求
        if (this.pendingRequests.has(key)) {
            console.log(`等待进行中的请求: ${key}`);
            return await this.pendingRequests.get(key);
        }
        
        // 创建新的请求
        const requestPromise = apiFunction().then(data => {
            this.cache.set(key, {
                data: data,
                timestamp: Date.now()
            });
            this.pendingRequests.delete(key);
            return data;
        }).catch(error => {
            this.pendingRequests.delete(key);
            throw error;
        });
        
        this.pendingRequests.set(key, requestPromise);
        return await requestPromise;
    }
    
    // 限流控制
    async rateLimitedAPICall(key, apiFunction, maxCalls = 10, timeWindow = 60000) {
        const now = Date.now();
        const rateLimit = this.rateLimits.get(key) || {
            calls: [],
            maxCalls: maxCalls,
            timeWindow: timeWindow
        };
        
        // 清理过期的调用记录
        rateLimit.calls = rateLimit.calls.filter(timestamp => 
            now - timestamp < timeWindow
        );
        
        // 检查是否超过限制
        if (rateLimit.calls.length >= maxCalls) {
            const oldestCall = Math.min(...rateLimit.calls);
            const waitTime = timeWindow - (now - oldestCall);
            
            console.log(`达到速率限制,等待 ${waitTime}ms`);
            await this.sleep(waitTime);
            
            return await this.rateLimitedAPICall(key, apiFunction, maxCalls, timeWindow);
        }
        
        // 记录这次调用
        rateLimit.calls.push(now);
        this.rateLimits.set(key, rateLimit);
        
        try {
            return await apiFunction();
        } catch (error) {
            // 调用失败时移除记录
            rateLimit.calls.pop();
            throw error;
        }
    }
    
    sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    // 清理缓存
    clearCache(key) {
        if (key) {
            this.cache.delete(key);
        } else {
            this.cache.clear();
        }
    }
}

// 使用示例
const apiOptimizer = new APIOptimizer();

// 缓存地理位置数据
async function getCachedLocation() {
    return await apiOptimizer.cachedAPICall(
        'user-location',
        () => {
            return new Promise((resolve, reject) => {
                navigator.geolocation.getCurrentPosition(
                    (position) => resolve(position.coords),
                    (error) => reject(error),
                    { maximumAge: 300000 } // 5分钟缓存
                );
            });
        },
        300000 // 5分钟TTL
    );
}

// 限流的通知发送
async function sendRateLimitedNotification(title, options) {
    return await apiOptimizer.rateLimitedAPICall(
        'notifications',
        () => {
            return new Promise((resolve, reject) => {
                const notification = new Notification(title, options);
                notification.onshow = () => resolve(notification);
                notification.onerror = () => reject(new Error('通知显示失败'));
            });
        },
        3, // 每分钟最多3个通知
        60000
    );
}
5.2 安全最佳实践
代码语言:javascript
复制
// 安全配置管理器
class SecurityManager {
    constructor() {
        this.permissions = new Map();
        this.securityPolicies = {
            clipboard: {
                requireHTTPS: true,
                requireUserGesture: true,
                maxTextLength: 10000
            },
            notification: {
                requireHTTPS: true,
                requireUserGesture: true,
                maxNotificationsPerMinute: 10
            },
            geolocation: {
                requireHTTPS: true,
                requireUserConsent: true,
                maxAccuracy: 1000 // 米
            }
        };
    }
    
    // 检查安全策略
    checkSecurityPolicy(apiName, options = {}) {
        const policy = this.securityPolicies[apiName];
        if (!policy) {
            return { allowed: true, reason: '无安全策略' };
        }
        
        // 检查HTTPS要求
        if (policy.requireHTTPS && !this.isHTTPS()) {
            return { allowed: false, reason: '需要HTTPS连接' };
        }
        
        // 检查用户手势要求
        if (policy.requireUserGesture && !this.hasUserGesture()) {
            return { allowed: false, reason: '需要用户交互' };
        }
        
        // API特定检查
        switch (apiName) {
            case 'clipboard':
                if (options.text && options.text.length > policy.maxTextLength) {
                    return { allowed: false, reason: '文本长度超出限制' };
                }
                break;
                
            case 'notification':
                const recentCount = this.getRecentNotificationCount();
                if (recentCount >= policy.maxNotificationsPerMinute) {
                    return { allowed: false, reason: '通知频率过高' };
                }
                break;
                
            case 'geolocation':
                if (options.enableHighAccuracy && policy.maxAccuracy) {
                    // 可以添加更精确的位置权限控制
                }
                break;
        }
        
        return { allowed: true, reason: '通过安全检査' };
    }
    
    isHTTPS() {
        return location.protocol === 'https:' || location.hostname === 'localhost';
    }
    
    hasUserGesture() {
        // 在实际应用中,这需要与事件系统结合
        // 这里简化处理,实际使用时需要在用户交互事件中调用API
        return true; // 假设总是有用户手势
    }
    
    getRecentNotificationCount() {
        const now = Date.now();
        const oneMinuteAgo = now - 60000;
        
        if (!this.recentNotifications) {
            this.recentNotifications = [];
        }
        
        // 清理过期记录
        this.recentNotifications = this.recentNotifications.filter(
            timestamp => timestamp > oneMinuteAgo
        );
        
        return this.recentNotifications.length;
    }
    
    recordNotification() {
        if (!this.recentNotifications) {
            this.recentNotifications = [];
        }
        
        this.recentNotifications.push(Date.now());
    }
    
    // 安全的API包装器
    async secureAPICall(apiName, apiFunction, options = {}) {
        const securityCheck = this.checkSecurityPolicy(apiName, options);
        
        if (!securityCheck.allowed) {
            throw new Error(`安全检査失败: ${securityCheck.reason}`);
        }
        
        try {
            // 记录敏感操作
            this.logSecurityEvent(apiName, 'attempt', options);
            
            const result = await apiFunction();
            
            // 记录成功操作
            this.logSecurityEvent(apiName, 'success', options);
            
            // 特殊处理
            if (apiName === 'notification') {
                this.recordNotification();
            }
            
            return result;
            
        } catch (error) {
            // 记录失败操作
            this.logSecurityEvent(apiName, 'error', { ...options, error: error.message });
            throw error;
        }
    }
    
    logSecurityEvent(apiName, action, details) {
        const event = {
            timestamp: new Date().toISOString(),
            api: apiName,
            action: action,
            details: details,
            userAgent: navigator.userAgent.substring(0, 100), // 限制长度
            url: window.location.href
        };
        
        // 在实际应用中,这可能发送到安全监控服务
        console.log('安全事件:', JSON.stringify(event));
        
        // 可以添加额外的安全监控逻辑
        if (action === 'error') {
            this.handleSecurityError(event);
        }
    }
    
    handleSecurityError(event) {
        // 处理安全错误,例如:
        // - 限制用户访问
        // - 增加额外的验证
        // - 通知管理员
        console.warn('安全错误处理:', event);
    }
}

// 创建安全管理器实例
const securityManager = new SecurityManager();

// 安全的通知发送
async function sendSecureNotification(title, options) {
    try {
        return await securityManager.secureAPICall(
            'notification',
            () => {
                return new Promise((resolve, reject) => {
                    const notification = new Notification(title, options);
                    notification.onshow = () => resolve(notification);
                    notification.onerror = () => reject(new Error('通知显示失败'));
                });
            },
            options
        );
    } catch (error) {
        console.error('安全的发送通知失败:', error);
        throw error;
    }
}

// 安全的剪贴板操作
async function secureClipboardOperation(operation, data) {
    try {
        if (operation === 'writeText') {
            return await securityManager.secureAPICall(
                'clipboard',
                () => navigator.clipboard.writeText(data),
                { text: data }
            );
        } else if (operation === 'readText') {
            return await securityManager.secureAPICall(
                'clipboard',
                () => navigator.clipboard.readText()
            );
        }
    } catch (error) {
        console.error('安全的剪贴板操作失败:', error);
        throw error;
    }
}

6. 实战项目:智能个人助理

6.1 项目架构
代码语言:javascript
复制
// 智能个人助理类
class SmartPersonalAssistant {
    constructor() {
        this.config = {
            enableNotifications: true,
            enableLocation: true,
            enableBatteryMonitor: true,
            maxNotifications: 5,
            locationUpdateInterval: 60000 // 1分钟
        };
        
        this.services = {
            notification: new NotificationManager(),
            location: new LocationManager(),
            battery: new BatteryManager(),
            network: new NetworkManager(),
            clipboard: new ClipboardManager()
        };
        
        this.init();
    }
    
    async init() {
        console.log('🚀 初始化智能个人助理...');
        
        // 检查权限
        await this.checkPermissions();
        
        // 初始化各个服务
        await this.initializeServices();
        
        // 设置事件监听
        this.setupEventListeners();
        
        console.log('✅ 智能个人助理初始化完成');
    }
    
    async checkPermissions() {
        const permissions = [
            { name: 'notifications', service: 'notification' },
            { name: 'geolocation', service: 'location' },
            { name: 'battery', service: 'battery' }
        ];
        
        for (const permission of permissions) {
            try {
                const result = await this.requestPermission(permission.name);
                console.log(`${permission.name} 权限:`, result);
                
                if (result === 'granted') {
                    this.config[`enable${permission.service.charAt(0).toUpperCase() + permission.service.slice(1)}`] = true;
                }
            } catch (error) {
                console.error(`获取 ${permission.name} 权限失败:`, error);
            }
        }
    }
    
    async requestPermission(permissionName) {
        switch (permissionName) {
            case 'notifications':
                return await Notification.requestPermission();
                
            case 'geolocation':
                return new Promise((resolve) => {
                    navigator.geolocation.getCurrentPosition(
                        () => resolve('granted'),
                        (error) => {
                            switch (error.code) {
                                case error.PERMISSION_DENIED:
                                    resolve('denied');
                                    break;
                                case error.POSITION_UNAVAILABLE:
                                case error.TIMEOUT:
                                    resolve('prompt');
                                    break;
                            }
                        }
                    );
                });
                
            case 'battery':
                if ('getBattery' in navigator) {
                    try {
                        await navigator.getBattery();
                        return 'granted';
                    } catch (error) {
                        return 'denied';
                    }
                }
                return 'unsupported';
                
            default:
                return 'unsupported';
        }
    }
    
    async initializeServices() {
        // 初始化通知服务
        if (this.config.enableNotifications) {
            await this.services.notification.init();
        }
        
        // 初始化位置服务
        if (this.config.enableLocation) {
            await this.services.location.init();
        }
        
        // 初始化电池监控
        if (this.config.enableBatteryMonitor) {
            await this.services.battery.init();
        }
        
        // 初始化网络监控
        await this.services.network.init();
        
        // 初始化剪贴板服务
        await this.services.clipboard.init();
    }
    
    setupEventListeners() {
        // 页面可见性变化
        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                console.log('页面隐藏,暂停非必要服务');
                this.pauseServices();
            } else {
                console.log('页面可见,恢复服务');
                this.resumeServices();
            }
        });
        
        // 网络状态变化
        window.addEventListener('online', () => {
            console.log('网络连接恢复');
            this.handleNetworkChange(true);
        });
        
        window.addEventListener('offline', () => {
            console.log('网络连接断开');
            this.handleNetworkChange(false);
        });
    }
    
    pauseServices() {
        this.services.location.pause();
        this.services.battery.pause();
    }
    
    resumeServices() {
        this.services.location.resume();
        this.services.battery.resume();
    }
    
    handleNetworkChange(isOnline) {
        if (isOnline) {
            // 网络恢复时的处理
            this.services.notification.send({
                title: '网络连接恢复',
                body: '您的网络连接已恢复,所有服务正常运行',
                icon: '/icons/online.png'
            });
        } else {
            // 网络断开时的处理
            this.services.notification.send({
                title: '网络连接断开',
                body: '检测到网络连接断开,部分功能可能受限',
                icon: '/icons/offline.png'
            });
        }
    }
    
    // 智能提醒功能
    async scheduleSmartReminder(time, message, options = {}) {
        const reminder = {
            id: Date.now().toString(),
            time: time,
            message: message,
            options: options,
            created: new Date()
        };
        
        // 设置定时器
        const delay = new Date(time) - new Date();
        
        if (delay > 0) {
            setTimeout(() => {
                this.triggerReminder(reminder);
            }, delay);
            
            console.log(`智能提醒已设置: ${message} (${new Date(time).toLocaleString()})`);
        }
    }
    
    async triggerReminder(reminder) {
        await this.services.notification.send({
            title: '智能提醒',
            body: reminder.message,
            icon: reminder.options.icon || '/icons/reminder.png',
            requireInteraction: true,
            actions: [
                { action: 'complete', title: '完成' },
                { action: 'snooze', title: '稍后提醒' }
            ]
        });
        
        // 处理用户响应
        if (reminder.options.onComplete) {
            reminder.options.onComplete();
        }
    }
    
    // 位置相关提醒
    async setupLocationReminder(location, message, radius = 100) {
        if (!this.config.enableLocation) {
            console.warn('位置服务未启用');
            return;
        }
        
        const reminder = {
            id: Date.now().toString(),
            location: location,
            message: message,
            radius: radius,
            created: new Date()
        };
        
        this.services.location.addLocationReminder(reminder);
        console.log(`位置提醒已设置: ${message} (半径: ${radius}米)`);
    }
    
    // 电池优化提醒
    async checkBatteryOptimization() {
        if (!this.config.enableBatteryMonitor) {
            return;
        }
        
        const batteryInfo = await this.services.battery.getInfo();
        
        if (batteryInfo.level < 0.2 && !batteryInfo.charging) {
            await this.services.notification.send({
                title: '电池电量低',
                body: `电池电量仅剩 ${Math.round(batteryInfo.level * 100)}%,建议充电`,
                icon: '/icons/battery-low.png',
                requireInteraction: true
            });
        }
        
        if (batteryInfo.charging && batteryInfo.level > 0.8) {
            await this.services.notification.send({
                title: '电池即将充满',
                body: `电池电量已达到 ${Math.round(batteryInfo.level * 100)}%`,
                icon: '/icons/battery-full.png'
            });
        }
    }
    
    // 智能复制助手
    async setupSmartClipboard() {
        if (!compatManager.isSupported('clipboard')) {
            console.warn('剪贴板API不支持');
            return;
        }
        
        // 监听剪贴板变化(需要用户交互触发)
        document.addEventListener('click', async () => {
            try {
                const text = await secureClipboardOperation('readText');
                
                // 智能分析剪贴板内容
                if (this.isURL(text)) {
                    console.log('检测到URL:', text);
                    // 可以自动打开预览或保存书签
                } else if (this.isEmail(text)) {
                    console.log('检测到邮箱:', text);
                    // 可以自动添加到联系人
                } else if (this.isPhoneNumber(text)) {
                    console.log('检测到电话号码:', text);
                    // 可以自动格式化或保存
                }
                
            } catch (error) {
                console.error('读取剪贴板失败:', error);
            }
        });
    }
    
    isURL(text) {
        const urlRegex = /^(https?:\\/\\/)?[\\w\\-]+(\\.[\\w\\-]+)+[/#?]?.*$/;
        return urlRegex.test(text);
    }
    
    isEmail(text) {
        const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;
        return emailRegex.test(text);
    }
    
    isPhoneNumber(text) {
        const phoneRegex = /^[\\+]?[1-9][\\d]{0,15}$/;
        return phoneRegex.test(text.replace(/[\\s\\-()]/g, ''));
    }
    
    // 获取系统状态报告
    async getSystemStatus() {
        const status = {
            timestamp: new Date().toISOString(),
            permissions: {
                notifications: Notification.permission,
                geolocation: await this.getGeolocationPermission()
            },
            services: {}
        };
        
        // 获取各个服务状态
        if (this.config.enableLocation) {
            status.services.location = await this.services.location.getStatus();
        }
        
        if (this.config.enableBatteryMonitor) {
            status.services.battery = await this.services.battery.getStatus();
        }
        
        status.services.network = this.services.network.getStatus();
        
        return status;
    }
    
    async getGeolocationPermission() {
        return new Promise((resolve) => {
            navigator.geolocation.getCurrentPosition(
                () => resolve('granted'),
                (error) => {
                    if (error.code === error.PERMISSION_DENIED) {
                        resolve('denied');
                    } else {
                        resolve('prompt');
                    }
                }
            );
        });
    }
}

// 各个服务管理器的简化实现
class NotificationManager {
    constructor() {
        this.notifications = [];
        this.maxNotifications = 5;
    }
    
    async init() {
        if (Notification.permission === 'default') {
            await Notification.requestPermission();
        }
    }
    
    async send(options) {
        if (Notification.permission !== 'granted') {
            console.warn('没有通知权限');
            return;
        }
        
        // 限制通知数量
        if (this.notifications.length >= this.maxNotifications) {
            const oldest = this.notifications.shift();
            oldest.close();
        }
        
        const notification = new Notification(options.title, {
            body: options.body,
            icon: options.icon,
            requireInteraction: options.requireInteraction || false
        });
        
        this.notifications.push(notification);
        
        notification.onclose = () => {
            const index = this.notifications.indexOf(notification);
            if (index > -1) {
                this.notifications.splice(index, 1);
            }
        };
    }
}

class LocationManager {
    constructor() {
        this.watchId = null;
        this.locationReminders = [];
    }
    
    async init() {
        // 初始化位置服务
    }
    
    pause() {
        if (this.watchId) {
            navigator.geolocation.clearWatch(this.watchId);
            this.watchId = null;
        }
    }
    
    resume() {
        if (!this.watchId) {
            this.watchId = navigator.geolocation.watchPosition(
                (position) => this.handlePositionUpdate(position),
                (error) => console.error('位置更新失败:', error)
            );
        }
    }
    
    addLocationReminder(reminder) {
        this.locationReminders.push(reminder);
    }
    
    handlePositionUpdate(position) {
        // 检查位置提醒
        this.locationReminders.forEach(reminder => {
            const distance = this.calculateDistance(
                position.coords,
                reminder.location
            );
            
            if (distance <= reminder.radius) {
                this.triggerLocationReminder(reminder);
            }
        });
    }
    
    calculateDistance(coords1, coords2) {
        // 简化的距离计算
        const R = 6371e3; // 地球半径(米)
        const φ1 = coords1.latitude * Math.PI / 180;
        const φ2 = coords2.latitude * Math.PI / 180;
        const Δφ = (coords2.latitude - coords1.latitude) * Math.PI / 180;
        const Δλ = (coords2.longitude - coords1.longitude) * Math.PI / 180;
        
        const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
                  Math.cos(φ1) * Math.cos(φ2) *
                  Math.sin(Δλ/2) * Math.sin(Δλ/2);
        const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        
        const d = R * c; // 距离(米)
        return d;
    }
    
    triggerLocationReminder(reminder) {
        // 触发位置提醒
        if (reminder.notification) {
            new Notification(reminder.notification.title, {
                body: reminder.notification.body,
                icon: reminder.notification.icon
            });
        }
        
        if (reminder.callback) {
            reminder.callback();
        }
    }
    
    async getStatus() {
        return {
            active: this.watchId !== null,
            reminders: this.locationReminders.length
        };
    }
}

class BatteryManager {
    constructor() {
        this.battery = null;
        this.listeners = [];
    }
    
    async init() {
        if (!navigator.getBattery) {
            return;
        }
        
        this.battery = await navigator.getBattery();
        this.setupListeners();
    }
    
    setupListeners() {
        this.battery.addEventListener('levelchange', () => {
            this.notifyListeners('levelchange', {
                level: this.battery.level,
                charging: this.battery.charging
            });
        });
        
        this.battery.addEventListener('chargingchange', () => {
            this.notifyListeners('chargingchange', {
                level: this.battery.level,
                charging: this.battery.charging
            });
        });
    }
    
    addListener(callback) {
        this.listeners.push(callback);
    }
    
    notifyListeners(event, data) {
        this.listeners.forEach(callback => callback(event, data));
    }
    
    getStatus() {
        if (!this.battery) {
            return { supported: false };
        }
        
        return {
            supported: true,
            level: this.battery.level,
            charging: this.battery.charging,
            chargingTime: this.battery.chargingTime,
            dischargingTime: this.battery.dischargingTime
        };
    }
}

class NetworkManager {
    constructor() {
        this.connection = null;
    }
    
    init() {
        this.connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
        
        if (this.connection) {
            this.connection.addEventListener('change', () => {
                console.log('网络状态变化:', this.getStatus());
            });
        }
    }
    
    getStatus() {
        if (!this.connection) {
            return { supported: false };
        }
        
        return {
            supported: true,
            effectiveType: this.connection.effectiveType,
            downlink: this.connection.downlink,
            rtt: this.connection.rtt,
            saveData: this.connection.saveData
        };
    }
}

// 初始化智能个人助理
async function initSmartAssistant() {
    const assistant = new SmartPersonalAssistant({
        enableLocation: true,
        enableBatteryMonitor: true,
        enableNetworkOptimization: true,
        enableClipboardAssistant: true
    });
    
    await assistant.init();
    
    // 添加一些示例提醒
    assistant.addSmartReminder({
        id: 'office-arrival',
        condition: 'location',
        location: { latitude: 40.7128, longitude: -74.0060 }, // 示例坐标
        radius: 100, // 100米范围
        message: '已到达办公地点,记得打卡!',
        notification: {
            title: '位置提醒',
            body: '已到达办公地点,记得打卡!',
            icon: '/icons/location.png'
        }
    });
    
    console.log('智能个人助理已启动');
    return assistant;
}

// 使用示例
// initSmartAssistant().then(assistant => {
//     console.log('助手已就绪');
// });

export { SmartPersonalAssistant, initSmartAssistant };

7. 浏览器兼容性处理

7.1 特性检测函数
代码语言:javascript
复制
// 浏览器兼容性检测
class CompatibilityManager {
    constructor() {
        this.supportedFeatures = new Map();
        this.init();
    }
    
    init() {
        this.checkAllFeatures();
    }
    
    checkAllFeatures() {
        // Clipboard API
        this.supportedFeatures.set('clipboard', 
            'clipboard' in navigator && 
            'writeText' in navigator.clipboard &&
            'readText' in navigator.clipboard
        );
        
        // Notification API
        this.supportedFeatures.set('notification', 
            'Notification' in window
        );
        
        // Geolocation API
        this.supportedFeatures.set('geolocation', 
            'geolocation' in navigator
        );
        
        // Battery API
        this.supportedFeatures.set('battery', 
            'getBattery' in navigator
        );
        
        // Network Information API
        this.supportedFeatures.set('network', 
            'connection' in navigator || 
            'mozConnection' in navigator || 
            'webkitConnection' in navigator
        );
        
        // Page Visibility API
        this.supportedFeatures.set('visibility', 
            'hidden' in document && 
            'visibilityState' in document
        );
        
        // Fullscreen API
        this.supportedFeatures.set('fullscreen', 
            'requestFullscreen' in document.documentElement ||
            'webkitRequestFullscreen' in document.documentElement ||
            'mozRequestFullScreen' in document.documentElement ||
            'msRequestFullscreen' in document.documentElement
        );
        
        // Service Worker
        this.supportedFeatures.set('serviceWorker', 
            'serviceWorker' in navigator
        );
        
        // HTTPS检测
        this.supportedFeatures.set('https', 
            location.protocol === 'https:' || 
            location.hostname === 'localhost'
        );
    }
    
    isSupported(feature) {
        return this.supportedFeatures.get(feature) || false;
    }
    
    getSupportedFeatures() {
        const supported = {};
        for (const [feature, supported] of this.supportedFeatures) {
            if (supported) {
                supported[feature] = true;
            }
        }
        return supported;
    }
    
    getUnsupportedFeatures() {
        const unsupported = {};
        for (const [feature, supported] of this.supportedFeatures) {
            if (!supported) {
                unsupported[feature] = false;
            }
        }
        return unsupported;
    }
    
    // 获取浏览器信息
    getBrowserInfo() {
        const ua = navigator.userAgent;
        let browser = 'Unknown';
        let version = 'Unknown';
        
        if (ua.indexOf('Chrome') > -1) {
            browser = 'Chrome';
            version = ua.match(/Chrome\/(\d+)/)[1];
        } else if (ua.indexOf('Firefox') > -1) {
            browser = 'Firefox';
            version = ua.match(/Firefox\/(\d+)/)[1];
        } else if (ua.indexOf('Safari') > -1) {
            browser = 'Safari';
            version = ua.match(/Version\/(\d+)/)[1];
        } else if (ua.indexOf('Edge') > -1) {
            browser = 'Edge';
            version = ua.match(/Edge\/(\d+)/)[1];
        }
        
        return { browser, version, userAgent: ua };
    }
    
    // 生成兼容性报告
    generateReport() {
        const report = {
            timestamp: new Date().toISOString(),
            browser: this.getBrowserInfo(),
            features: {
                supported: this.getSupportedFeatures(),
                unsupported: this.getUnsupportedFeatures()
            },
            recommendations: this.getRecommendations()
        };
        
        return report;
    }
    
    getRecommendations() {
        const recommendations = [];
        const unsupported = this.getUnsupportedFeatures();
        
        if (unsupported.clipboard) {
            recommendations.push({
                feature: 'Clipboard API',
                recommendation: '使用 document.execCommand 作为降级方案',
                priority: 'high'
            });
        }
        
        if (unsupported.notification) {
            recommendations.push({
                feature: 'Notification API',
                recommendation: '使用页面内通知或模态框替代',
                priority: 'medium'
            });
        }
        
        if (unsupported.https) {
            recommendations.push({
                feature: 'HTTPS',
                recommendation: '某些API需要HTTPS环境,考虑升级到HTTPS',
                priority: 'high'
            });
        }
        
        return recommendations;
    }
}

// 使用示例
const compatManager = new CompatibilityManager();
console.log('兼容性报告:', compatManager.generateReport());
7.2 降级方案实现
代码语言:javascript
复制
// API降级处理器
class FallbackHandler {
    constructor(compatibilityManager) {
        this.compat = compatibilityManager;
    }
    
    // 剪贴板降级方案
    async copyText(text) {
        if (this.compat.isSupported('clipboard')) {
            try {
                await navigator.clipboard.writeText(text);
                return { success: true, method: 'modern' };
            } catch (error) {
                console.warn('现代剪贴板API失败,尝试降级方案');
            }
        }
        
        // 降级方案
        return this.fallbackCopyText(text);
    }
    
    fallbackCopyText(text) {
        const textArea = document.createElement('textarea');
        textArea.value = text;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        textArea.style.top = '-999999px';
        
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        
        let success = false;
        try {
            success = document.execCommand('copy');
        } catch (error) {
            console.error('降级复制失败:', error);
        }
        
        document.body.removeChild(textArea);
        
        return { success, method: 'fallback' };
    }
    
    // 通知降级方案
    showNotification(title, options = {}) {
        if (this.compat.isSupported('notification') && Notification.permission === 'granted') {
            try {
                return new Notification(title, options);
            } catch (error) {
                console.warn('现代通知API失败,使用降级方案');
            }
        }
        
        // 降级方案:使用页面内通知
        return this.fallbackNotification(title, options);
    }
    
    fallbackNotification(title, options) {
        // 创建页面内通知元素
        const notification = document.createElement('div');
        notification.className = 'fallback-notification';
        notification.innerHTML = `
            <div class="notification-content">
                <h4>${title}</h4>
                ${options.body ? `<p>${options.body}</p>` : ''}
                <button onclick="this.parentElement.parentElement.remove()">关闭</button>
            </div>
        `;
        
        // 添加样式
        const style = document.createElement('style');
        style.textContent = `
            .fallback-notification {
                position: fixed;
                top: 20px;
                right: 20px;
                background: white;
                border-radius: 8px;
                box-shadow: 0 4px 12px rgba(0,0,0,0.15);
                padding: 16px;
                max-width: 300px;
                z-index: 10000;
                animation: slideIn 0.3s ease;
            }
            
            .notification-content h4 {
                margin: 0 0 8px 0;
                color: #333;
            }
            
            .notification-content p {
                margin: 0 0 12px 0;
                color: #666;
            }
            
            .notification-content button {
                background: #007bff;
                color: white;
                border: none;
                padding: 6px 12px;
                border-radius: 4px;
                cursor: pointer;
            }
            
            @keyframes slideIn {
                from { transform: translateX(100%); opacity: 0; }
                to { transform: translateX(0); opacity: 1; }
            }
        `;
        
        if (!document.querySelector('.fallback-notification-styles')) {
            style.className = 'fallback-notification-styles';
            document.head.appendChild(style);
        }
        
        document.body.appendChild(notification);
        
        // 自动关闭
        if (options.timeout !== false) {
            setTimeout(() => {
                if (notification.parentElement) {
                    notification.remove();
                }
            }, options.timeout || 5000);
        }
        
        return notification;
    }
    
    // 地理位置降级方案
    getCurrentPosition(options = {}) {
        return new Promise((resolve, reject) => {
            if (this.compat.isSupported('geolocation')) {
                navigator.geolocation.getCurrentPosition(resolve, reject, options);
            } else {
                reject(new Error('Geolocation API 不支持'));
            }
        });
    }
}

// 使用示例
const fallbackHandler = new FallbackHandler(compatManager);

// 使用降级方案复制文本
fallbackHandler.copyText('要复制的文本').then(result => {
    console.log('复制结果:', result);
});

// 使用降级方案显示通知
fallbackHandler.showNotification('标题', { body: '内容' });

8. 性能优化与安全考虑

8.1 API调用优化器
代码语言:javascript
复制
// API调用优化器
class APIOptimizer {
    constructor() {
        this.cache = new Map();
        this.rateLimiters = new Map();
        this.pendingRequests = new Map();
    }
    
    // 缓存包装器
    withCache(key, fetcher, ttl = 60000) {
        const cached = this.cache.get(key);
        if (cached && Date.now() - cached.timestamp < ttl) {
            return Promise.resolve(cached.data);
        }
        
        return fetcher().then(data => {
            this.cache.set(key, {
                data,
                timestamp: Date.now()
            });
            return data;
        });
    }
    
    // 限流包装器
    withRateLimit(key, limit, window, fn) {
        const limiter = this.getRateLimiter(key, limit, window);
        
        return new Promise((resolve, reject) => {
            if (limiter.tryConsume()) {
                fn().then(resolve).catch(reject);
            } else {
                reject(new Error('Rate limit exceeded'));
            }
        });
    }
    
    getRateLimiter(key, limit, window) {
        if (!this.rateLimiters.has(key)) {
            this.rateLimiters.set(key, new RateLimiter(limit, window));
        }
        return this.rateLimiters.get(key);
    }
    
    // 防抖包装器
    debounce(key, delay, fn) {
        clearTimeout(this.debounceTimers?.[key]);
        
        if (!this.debounceTimers) {
            this.debounceTimers = {};
        }
        
        return new Promise((resolve) => {
            this.debounceTimers[key] = setTimeout(() => {
                resolve(fn());
            }, delay);
        });
    }
    
    // 请求去重
    dedupe(key, fn) {
        if (this.pendingRequests.has(key)) {
            return this.pendingRequests.get(key);
        }
        
        const promise = fn().finally(() => {
            this.pendingRequests.delete(key);
        });
        
        this.pendingRequests.set(key, promise);
        return promise;
    }
    
    // 清理缓存
    clearCache(pattern) {
        if (pattern) {
            for (const key of this.cache.keys()) {
                if (key.includes(pattern)) {
                    this.cache.delete(key);
                }
            }
        } else {
            this.cache.clear();
        }
    }
}

// 限流器类
class RateLimiter {
    constructor(limit, window) {
        this.limit = limit;
        this.window = window;
        this.tokens = limit;
        this.lastRefill = Date.now();
    }
    
    tryConsume() {
        this.refill();
        
        if (this.tokens >= 1) {
            this.tokens--;
            return true;
        }
        
        return false;
    }
    
    refill() {
        const now = Date.now();
        const timePassed = now - this.lastRefill;
        const tokensToAdd = Math.floor((timePassed / this.window) * this.limit);
        
        if (tokensToAdd > 0) {
            this.tokens = Math.min(this.limit, this.tokens + tokensToAdd);
            this.lastRefill = now;
        }
    }
}
8.2 安全配置管理器
代码语言:javascript
复制
// 安全配置管理器
class SecurityManager {
    constructor() {
        this.config = {
            requireHTTPS: true,
            requireUserGesture: true,
            allowedOrigins: [],
            blockedOrigins: [],
            maxNotifications: 10,
            maxLocationAccuracy: 1000, // 米
            enableLogging: true
        };
    }
    
    // 检查HTTPS
    checkHTTPS() {
        if (this.config.requireHTTPS && 
            location.protocol !== 'https:' && 
            location.hostname !== 'localhost') {
            throw new Error('此功能需要HTTPS环境');
        }
        return true;
    }
    
    // 检查用户手势
    checkUserGesture() {
        if (this.config.requireUserGesture) {
            // 检查当前事件是否是用户手势触发的
            return this.isUserGesture();
        }
        return true;
    }
    
    isUserGesture() {
        // 简化的用户手势检测
        // 在实际应用中,这需要更复杂的检测逻辑
        return true; // 假设当前调用是用户手势触发的
    }
    
    // 验证来源
    validateOrigin(origin) {
        if (this.config.blockedOrigins.includes(origin)) {
            throw new Error('来源被阻止');
        }
        
        if (this.config.allowedOrigins.length > 0 && 
            !this.config.allowedOrigins.includes(origin)) {
            throw new Error('来源不在允许列表中');
        }
        
        return true;
    }
    
    // 权限验证包装器
    async withPermissionCheck(permission, fn) {
        try {
            this.checkHTTPS();
            this.checkUserGesture();
            
            if (permission) {
                const result = await navigator.permissions.query({ name: permission });
                if (result.state === 'denied') {
                    throw new Error(`权限被拒绝: ${permission}`);
                }
            }
            
            return await fn();
        } catch (error) {
            this.logSecurityEvent('permission_denied', { permission, error: error.message });
            throw error;
        }
    }
    
    // 安全包装器
    secureExecute(feature, fn) {
        return this.withPermissionCheck(null, async () => {
            try {
                const result = await fn();
                this.logSecurityEvent('feature_used', { feature, success: true });
                return result;
            } catch (error) {
                this.logSecurityEvent('feature_error', { feature, error: error.message });
                throw error;
            }
        });
    }
    
    // 日志记录
    logSecurityEvent(event, data) {
        if (this.config.enableLogging) {
            console.log(`[Security] ${event}:`, data);
            
            // 可以发送到远程日志服务
            this.sendToLogService(event, data);
        }
    }
    
    sendToLogService(event, data) {
        // 发送到远程日志服务的逻辑
        // fetch('/api/security-logs', { method: 'POST', body: JSON.stringify({ event, data }) });
    }
    
    // 更新配置
    updateConfig(newConfig) {
        this.config = { ...this.config, ...newConfig };
    }
}

// 使用示例
const securityManager = new SecurityManager();

// 安全地使用剪贴板API
async function secureClipboardOperation(operation, data) {
    return securityManager.secureExecute('clipboard', async () => {
        switch (operation) {
            case 'writeText':
                return await navigator.clipboard.writeText(data);
            case 'readText':
                return await navigator.clipboard.readText();
            default:
                throw new Error('不支持的操作');
        }
    });
}

9. 最佳实践总结

9.1 通用最佳实践
  1. 始终检查API支持:在使用任何API之前,先检查浏览器支持情况
  2. 处理权限请求:正确请求和处理用户权限
  3. 提供降级方案:为不支持API的浏览器提供替代方案
  4. 错误处理:完善的错误处理和用户反馈
  5. 性能优化:使用缓存、限流等优化策略
  6. 安全考虑:确保HTTPS、用户手势等安全要求
9.2 具体API使用建议

Clipboard API:

  • 始终在用户手势触发时使用
  • 提供复制成功的视觉反馈
  • 处理权限被拒绝的情况
  • 使用降级方案支持旧浏览器

Notification API:

  • 不要滥用通知权限
  • 提供有价值的内容
  • 允许用户控制通知频率
  • 考虑使用Service Worker增强功能

Geolocation API:

  • 明确告知用户位置信息的用途
  • 提供高精度选项的控制
  • 处理位置服务被禁用的情况
  • 考虑电池消耗影响
9.3 调试技巧
代码语言:javascript
复制
// 调试工具
class APIDebugger {
    constructor() {
        this.logs = [];
        this.isEnabled = false;
    }
    
    enable() {
        this.isEnabled = true;
        console.log('API调试器已启用');
    }
    
    disable() {
        this.isEnabled = false;
    }
    
    log(api, operation, data) {
        if (!this.isEnabled) return;
        
        const logEntry = {
            timestamp: new Date().toISOString(),
            api,
            operation,
            data,
            userAgent: navigator.userAgent,
            url: window.location.href
        };
        
        this.logs.push(logEntry);
        console.log(`[${api}] ${operation}:`, data);
        
        // 保持日志数量限制
        if (this.logs.length > 100) {
            this.logs.shift();
        }
    }
    
    exportLogs() {
        return JSON.stringify(this.logs, null, 2);
    }
    
    clearLogs() {
        this.logs = [];
    }
}

// 全局调试器实例
window.apiDebugger = new APIDebugger();

结语

浏览器原生API为前端开发提供了强大的功能,让我们能够创建更加丰富和交互性强的Web应用。通过本文的学习,你应该已经掌握了:

  1. 如何使用Clipboard API实现现代化的复制粘贴功能
  2. 如何使用Notification API创建桌面通知系统
  3. 如何结合多个API创建智能的个人助理应用
  4. 如何处理浏览器兼容性和提供降级方案
  5. 如何优化性能并确保安全性

记住,使用这些API时要始终以用户体验为中心,合理使用权限,提供有价值的功能。随着Web技术的不断发展,浏览器原生API会变得越来越强大,为我们的应用开发提供更多可能性。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 浏览器原生API实战:Clipboard API、Notification API与更多实用API详解
    • 前言
    • 1. Clipboard API - 剪贴板操作的艺术
      • 1.1 基础概念
      • 1.2 核心方法与属性
      • 1.3 实战案例:智能复制按钮
      • 1.4 高级用法:复制富文本和HTML
      • 1.5 权限管理
    • 2. Notification API - 桌面通知系统
      • 2.1 基础概念
      • 2.2 权限请求与基础使用
      • 2.3 实战案例:智能通知系统
      • 2.4 通知最佳实践
    • 3. 其他实用浏览器原生API
      • 3.1 Geolocation API - 地理位置获取
      • 3.2 Battery API - 电池状态监控
      • 3.3 Network Information API - 网络状态检测
      • 3.4 Page Visibility API - 页面可见性检测
      • 3.5 Fullscreen API - 全屏模式控制
    • 4. 浏览器兼容性处理
      • 4.1 特性检测与降级方案
      • 4.2 浏览器版本检测
    • 5. 性能优化与安全考虑
      • 5.1 性能优化策略
      • 5.2 安全最佳实践
    • 6. 实战项目:智能个人助理
      • 6.1 项目架构
    • 7. 浏览器兼容性处理
      • 7.1 特性检测函数
      • 7.2 降级方案实现
    • 8. 性能优化与安全考虑
      • 8.1 API调用优化器
      • 8.2 安全配置管理器
    • 9. 最佳实践总结
      • 9.1 通用最佳实践
      • 9.2 具体API使用建议
      • 9.3 调试技巧
    • 结语
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档