Skip to content

history对象详解2024:JavaScript开发者掌握浏览器历史记录管理完整指南

📊 SEO元描述:2024年最新history对象教程,详解pushState、replaceState、历史记录操作、SPA路由实现。包含完整代码示例,适合JavaScript开发者掌握现代Web应用路由技术。

核心关键词:history对象、pushState、replaceState、SPA路由、浏览器历史记录

长尾关键词:history对象怎么用、pushState用法、JavaScript路由、单页应用路由、浏览器历史管理


📚 history对象学习目标与核心收获

通过本节history对象详解,你将系统性掌握:

  • 历史记录操作 :掌握浏览器历史记录的基本操作方法
  • pushState和replaceState :深入理解现代历史记录管理API
  • SPA路由实现 :构建单页应用的路由系统基础
  • 状态管理 :实现页面状态的保存和恢复机制
  • 用户体验优化 :提供流畅的页面导航体验
  • SEO友好的路由 :实现对搜索引擎友好的URL管理

🎯 适合人群

  • 前端开发者的SPA路由系统构建需求
  • Web应用开发者的页面导航优化需求
  • JavaScript高级学习者的现代Web API掌握需求
  • 单页应用架构师的路由设计和实现需求

🌟 history对象是什么?为什么要掌握历史记录管理?

history对象是什么?这是现代Web应用开发的核心技术。history对象是浏览器提供的历史记录管理接口,也是单页应用路由系统的技术基础。

history对象的核心价值

  • 🎯 无刷新导航:实现页面间的无刷新跳转
  • 🔧 状态保持:保存和恢复页面状态信息
  • 💡 SEO优化:提供搜索引擎友好的URL结构
  • 📚 用户体验:提供流畅的页面导航体验
  • 🚀 现代架构:支持单页应用的路由管理

💡 学习建议:history对象是现代Web开发的基础,掌握它对于构建高质量的单页应用至关重要

history对象的基本操作

传统历史记录方法

history对象 提供了基本的历史记录操作方法:

javascript
// 🎉 history对象基本操作示例
class BasicHistoryManager {
    constructor() {
        this.init();
    }
    
    // 初始化历史记录管理
    init() {
        console.log('历史记录长度:', history.length);
        this.setupEventListeners();
    }
    
    // 后退操作
    goBack(steps = 1) {
        if (steps === 1) {
            history.back();
        } else {
            history.go(-steps);
        }
        console.log(`后退 ${steps} 步`);
    }
    
    // 前进操作
    goForward(steps = 1) {
        if (steps === 1) {
            history.forward();
        } else {
            history.go(steps);
        }
        console.log(`前进 ${steps} 步`);
    }
    
    // 跳转到指定位置
    goToPosition(position) {
        history.go(position);
        console.log(`跳转到位置: ${position}`);
    }
    
    // 获取历史记录信息
    getHistoryInfo() {
        return {
            length: history.length,
            state: history.state,
            canGoBack: history.length > 1,
            canGoForward: false // 无法直接检测
        };
    }
    
    // 设置事件监听器
    setupEventListeners() {
        // 监听popstate事件(用户点击前进/后退按钮)
        window.addEventListener('popstate', (event) => {
            console.log('历史记录变化:', event.state);
            this.handlePopState(event);
        });
        
        // 监听beforeunload事件(页面即将卸载)
        window.addEventListener('beforeunload', (event) => {
            console.log('页面即将卸载');
            this.handleBeforeUnload(event);
        });
    }
    
    // 处理popstate事件
    handlePopState(event) {
        const state = event.state;
        if (state) {
            console.log('恢复状态:', state);
            this.restoreState(state);
        } else {
            console.log('没有状态信息');
        }
    }
    
    // 处理页面卸载前事件
    handleBeforeUnload(event) {
        // 可以在这里保存当前状态
        this.saveCurrentState();
    }
    
    // 恢复状态
    restoreState(state) {
        // 根据状态信息恢复页面
        if (state.scrollPosition) {
            window.scrollTo(state.scrollPosition.x, state.scrollPosition.y);
        }
        
        if (state.formData) {
            this.restoreFormData(state.formData);
        }
    }
    
    // 保存当前状态
    saveCurrentState() {
        const state = {
            timestamp: Date.now(),
            url: location.href,
            scrollPosition: {
                x: window.pageXOffset,
                y: window.pageYOffset
            },
            formData: this.getFormData()
        };
        
        // 保存到sessionStorage作为备份
        try {
            sessionStorage.setItem('lastState', JSON.stringify(state));
        } catch (error) {
            console.warn('无法保存状态到sessionStorage:', error);
        }
    }
    
    // 获取表单数据
    getFormData() {
        const forms = document.querySelectorAll('form');
        const formData = {};
        
        forms.forEach((form, index) => {
            const data = new FormData(form);
            formData[`form_${index}`] = Object.fromEntries(data);
        });
        
        return formData;
    }
    
    // 恢复表单数据
    restoreFormData(formData) {
        Object.entries(formData).forEach(([formKey, data]) => {
            const formIndex = parseInt(formKey.split('_')[1]);
            const form = document.querySelectorAll('form')[formIndex];
            
            if (form) {
                Object.entries(data).forEach(([name, value]) => {
                    const input = form.querySelector(`[name="${name}"]`);
                    if (input) {
                        input.value = value;
                    }
                });
            }
        });
    }
}

// 使用基本历史记录管理器
const basicHistory = new BasicHistoryManager();

// 示例操作
console.log('历史记录信息:', basicHistory.getHistoryInfo());

// 创建一些导航按钮
function createNavigationButtons() {
    const nav = document.createElement('div');
    nav.innerHTML = `
        <button onclick="basicHistory.goBack()">后退</button>
        <button onclick="basicHistory.goForward()">前进</button>
        <button onclick="basicHistory.goBack(2)">后退2步</button>
        <button onclick="basicHistory.goToPosition(-1)">跳转到上一页</button>
    `;
    document.body.appendChild(nav);
}

// createNavigationButtons();

pushState和replaceState详解

javascript
// 🎉 pushState和replaceState详解示例
class ModernHistoryManager {
    constructor() {
        this.currentState = null;
        this.stateHistory = [];
        this.init();
    }
    
    // 初始化现代历史记录管理
    init() {
        // 设置初始状态
        this.setInitialState();
        this.setupEventListeners();
    }
    
    // 设置初始状态
    setInitialState() {
        const initialState = {
            page: 'home',
            timestamp: Date.now(),
            data: {
                title: document.title,
                url: location.href
            }
        };
        
        // 替换当前历史记录项
        this.replaceState(initialState, document.title, location.href);
    }
    
    // pushState - 添加新的历史记录项
    pushState(state, title, url) {
        try {
            // 验证参数
            if (!this.validateState(state)) {
                throw new Error('无效的状态对象');
            }
            
            if (!this.validateURL(url)) {
                throw new Error('无效的URL');
            }
            
            // 保存到内部历史记录
            this.stateHistory.push({
                state: { ...state },
                title: title,
                url: url,
                timestamp: Date.now()
            });
            
            // 调用浏览器API
            history.pushState(state, title, url);
            this.currentState = state;
            
            // 触发自定义事件
            this.dispatchStateChange('push', state, title, url);
            
            console.log('pushState成功:', { state, title, url });
            
        } catch (error) {
            console.error('pushState失败:', error);
            throw error;
        }
    }
    
    // replaceState - 替换当前历史记录项
    replaceState(state, title, url) {
        try {
            // 验证参数
            if (!this.validateState(state)) {
                throw new Error('无效的状态对象');
            }
            
            if (!this.validateURL(url)) {
                throw new Error('无效的URL');
            }
            
            // 更新内部历史记录
            if (this.stateHistory.length > 0) {
                this.stateHistory[this.stateHistory.length - 1] = {
                    state: { ...state },
                    title: title,
                    url: url,
                    timestamp: Date.now()
                };
            }
            
            // 调用浏览器API
            history.replaceState(state, title, url);
            this.currentState = state;
            
            // 触发自定义事件
            this.dispatchStateChange('replace', state, title, url);
            
            console.log('replaceState成功:', { state, title, url });
            
        } catch (error) {
            console.error('replaceState失败:', error);
            throw error;
        }
    }
    
    // 验证状态对象
    validateState(state) {
        if (state === null) return true;
        
        if (typeof state !== 'object') return false;
        
        // 检查状态对象大小(浏览器限制)
        try {
            const stateString = JSON.stringify(state);
            if (stateString.length > 640 * 1024) { // 640KB限制
                console.warn('状态对象过大,可能被浏览器拒绝');
                return false;
            }
        } catch (error) {
            console.warn('状态对象无法序列化:', error);
            return false;
        }
        
        return true;
    }
    
    // 验证URL
    validateURL(url) {
        if (!url) return false;
        
        try {
            const urlObj = new URL(url, location.origin);
            // 只允许同源URL
            return urlObj.origin === location.origin;
        } catch (error) {
            return false;
        }
    }
    
    // 导航到指定页面
    navigateTo(page, data = {}, title = '') {
        const state = {
            page: page,
            data: data,
            timestamp: Date.now(),
            id: this.generateStateId()
        };
        
        const url = this.buildURL(page, data);
        const pageTitle = title || this.generateTitle(page);
        
        this.pushState(state, pageTitle, url);
        
        // 更新页面内容
        this.updatePageContent(page, data);
        
        // 更新页面标题
        if (pageTitle) {
            document.title = pageTitle;
        }
    }
    
    // 替换当前页面状态
    updateCurrentPage(page, data = {}, title = '') {
        const state = {
            page: page,
            data: data,
            timestamp: Date.now(),
            id: this.currentState?.id || this.generateStateId()
        };
        
        const url = this.buildURL(page, data);
        const pageTitle = title || this.generateTitle(page);
        
        this.replaceState(state, pageTitle, url);
        
        // 更新页面内容
        this.updatePageContent(page, data);
        
        // 更新页面标题
        if (pageTitle) {
            document.title = pageTitle;
        }
    }
    
    // 构建URL
    buildURL(page, data = {}) {
        const basePath = location.pathname.split('/').slice(0, -1).join('/');
        let url = `${basePath}/${page}`;
        
        // 添加查询参数
        const params = new URLSearchParams();
        Object.entries(data).forEach(([key, value]) => {
            if (value !== null && value !== undefined) {
                params.append(key, value);
            }
        });
        
        const queryString = params.toString();
        if (queryString) {
            url += `?${queryString}`;
        }
        
        return url;
    }
    
    // 生成页面标题
    generateTitle(page) {
        const titleMap = {
            home: '首页',
            about: '关于我们',
            products: '产品列表',
            contact: '联系我们'
        };
        
        return titleMap[page] || `${page} - 我的网站`;
    }
    
    // 生成状态ID
    generateStateId() {
        return `state_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }
    
    // 更新页面内容
    updatePageContent(page, data) {
        // 这里应该根据实际应用实现页面内容更新逻辑
        console.log(`更新页面内容: ${page}`, data);
        
        // 示例:更新页面主要内容区域
        const contentArea = document.getElementById('main-content');
        if (contentArea) {
            contentArea.innerHTML = this.generatePageHTML(page, data);
        }
        
        // 更新导航状态
        this.updateNavigationState(page);
    }
    
    // 生成页面HTML
    generatePageHTML(page, data) {
        const templates = {
            home: `<h1>欢迎来到首页</h1><p>这是首页内容</p>`,
            about: `<h1>关于我们</h1><p>这是关于页面</p>`,
            products: `<h1>产品列表</h1><p>产品数据: ${JSON.stringify(data)}</p>`,
            contact: `<h1>联系我们</h1><p>联系信息</p>`
        };
        
        return templates[page] || `<h1>${page}</h1><p>页面内容</p>`;
    }
    
    // 更新导航状态
    updateNavigationState(currentPage) {
        const navLinks = document.querySelectorAll('nav a');
        navLinks.forEach(link => {
            const page = link.getAttribute('data-page');
            link.classList.toggle('active', page === currentPage);
        });
    }
    
    // 设置事件监听器
    setupEventListeners() {
        // 监听popstate事件
        window.addEventListener('popstate', (event) => {
            this.handlePopState(event);
        });
        
        // 监听页面可见性变化
        document.addEventListener('visibilitychange', () => {
            if (document.visibilityState === 'visible') {
                this.handlePageVisible();
            } else {
                this.handlePageHidden();
            }
        });
    }
    
    // 处理popstate事件
    handlePopState(event) {
        const state = event.state;
        
        if (state) {
            console.log('恢复状态:', state);
            this.currentState = state;
            
            // 恢复页面内容
            this.updatePageContent(state.page, state.data);
            
            // 恢复页面标题
            const title = this.generateTitle(state.page);
            document.title = title;
            
            // 触发自定义事件
            this.dispatchStateChange('pop', state, title, location.href);
            
        } else {
            console.log('没有状态信息,可能是初始页面');
            this.handleInitialPage();
        }
    }
    
    // 处理初始页面
    handleInitialPage() {
        // 从URL解析页面信息
        const pathParts = location.pathname.split('/').filter(part => part);
        const page = pathParts[pathParts.length - 1] || 'home';
        
        // 从查询参数解析数据
        const params = new URLSearchParams(location.search);
        const data = Object.fromEntries(params);
        
        // 更新页面
        this.updateCurrentPage(page, data);
    }
    
    // 处理页面可见
    handlePageVisible() {
        console.log('页面变为可见');
        // 可以在这里恢复定时器、动画等
    }
    
    // 处理页面隐藏
    handlePageHidden() {
        console.log('页面变为隐藏');
        // 可以在这里暂停定时器、动画等
        this.saveCurrentState();
    }
    
    // 保存当前状态
    saveCurrentState() {
        if (this.currentState) {
            try {
                sessionStorage.setItem('currentState', JSON.stringify(this.currentState));
            } catch (error) {
                console.warn('无法保存当前状态:', error);
            }
        }
    }
    
    // 触发状态变化事件
    dispatchStateChange(type, state, title, url) {
        const event = new CustomEvent('statechange', {
            detail: {
                type: type, // 'push', 'replace', 'pop'
                state: state,
                title: title,
                url: url,
                timestamp: Date.now()
            }
        });
        
        window.dispatchEvent(event);
    }
    
    // 获取历史记录信息
    getHistoryInfo() {
        return {
            currentState: this.currentState,
            historyLength: history.length,
            internalHistory: this.stateHistory,
            canGoBack: this.stateHistory.length > 1
        };
    }
    
    // 清理资源
    destroy() {
        // 移除事件监听器
        window.removeEventListener('popstate', this.handlePopState);
        document.removeEventListener('visibilitychange', this.handlePageVisible);
        
        // 清理内部状态
        this.stateHistory = [];
        this.currentState = null;
    }
}

// 使用现代历史记录管理器
const modernHistory = new ModernHistoryManager();

// 监听状态变化事件
window.addEventListener('statechange', (event) => {
    console.log('状态变化:', event.detail);
});

// 示例导航操作
function setupSPANavigation() {
    // 创建导航菜单
    const nav = document.createElement('nav');
    nav.innerHTML = `
        <a href="#" data-page="home">首页</a>
        <a href="#" data-page="about">关于</a>
        <a href="#" data-page="products">产品</a>
        <a href="#" data-page="contact">联系</a>
    `;
    
    // 添加点击事件
    nav.addEventListener('click', (event) => {
        event.preventDefault();
        const page = event.target.getAttribute('data-page');
        if (page) {
            modernHistory.navigateTo(page, { from: 'navigation' });
        }
    });
    
    document.body.appendChild(nav);
    
    // 创建内容区域
    const content = document.createElement('div');
    content.id = 'main-content';
    document.body.appendChild(content);
}

// setupSPANavigation();

核心应用场景

  • 🎯 SPA路由:构建单页应用的路由系统
  • 🎯 状态管理:保存和恢复页面状态信息
  • 🎯 用户体验:提供流畅的页面导航体验
  • 🎯 SEO优化:实现搜索引擎友好的URL结构

💼 开发价值:history对象是现代Web应用的核心技术,掌握它能让你构建高质量的单页应用


📚 history对象学习总结与下一步规划

✅ 本节核心收获回顾

通过本节history对象详解的学习,你已经掌握:

  1. 基本历史记录操作 :掌握back()、forward()、go()等传统方法
  2. pushState和replaceState :深入理解现代历史记录管理API
  3. 状态对象管理 :实现复杂的页面状态保存和恢复机制
  4. SPA路由基础 :构建单页应用路由系统的核心技术
  5. 事件处理机制 :处理popstate等历史记录相关事件

🎯 history对象下一步

  1. 完整SPA路由系统:基于history对象构建完整的路由框架
  2. 状态持久化:实现状态的本地存储和恢复机制
  3. SEO优化:结合服务端渲染优化SPA的SEO表现
  4. 性能优化:优化路由切换和状态管理的性能

🔗 相关学习资源

  • React Router源码:学习专业路由库的实现原理
  • Vue Router文档:了解Vue生态的路由解决方案
  • History API规范:深入了解浏览器历史记录API标准
  • SPA最佳实践:学习单页应用开发的最佳实践

💪 实践建议

  1. 路由库开发:开发一个完整的SPA路由库
  2. 状态管理系统:实现基于history的状态管理方案
  3. SEO优化实践:在实际项目中优化SPA的SEO表现
  4. 用户体验优化:提升页面导航的流畅性和响应速度

🔍 常见问题FAQ

Q1: pushState和replaceState有什么区别?

A: pushState会在历史记录中添加新条目,用户可以通过后退按钮返回;replaceState会替换当前历史记录条目,不会增加历史记录长度。

Q2: 状态对象有大小限制吗?

A: 是的,不同浏览器有不同限制,通常在640KB左右。建议保持状态对象简洁,避免存储大量数据。

Q3: 如何处理浏览器不支持History API的情况?

A: 可以使用hash路由作为降级方案,或者使用polyfill库。现代浏览器基本都支持History API。

Q4: popstate事件什么时候触发?

A: 当用户点击浏览器的前进/后退按钮,或者调用history.back()、history.forward()、history.go()时触发。

Q5: 如何实现SPA的SEO优化?

A: 结合服务端渲染(SSR)、预渲染、或者使用动态渲染技术,确保搜索引擎能够正确抓取页面内容。


🛠️ 实际应用案例

完整的SPA路由系统

javascript
// 🎉 完整的SPA路由系统
class SPARouter {
    constructor(options = {}) {
        this.routes = new Map();
        this.middlewares = [];
        this.currentRoute = null;
        this.options = {
            mode: 'history', // 'history' or 'hash'
            base: '/',
            ...options
        };
        
        this.init();
    }
    
    // 初始化路由系统
    init() {
        this.setupEventListeners();
        this.handleInitialRoute();
    }
    
    // 注册路由
    route(path, handler, options = {}) {
        const route = {
            path: path,
            handler: handler,
            options: options,
            params: {},
            query: {}
        };
        
        this.routes.set(path, route);
        return this;
    }
    
    // 注册中间件
    use(middleware) {
        this.middlewares.push(middleware);
        return this;
    }
    
    // 导航到指定路径
    push(path, state = {}) {
        const route = this.matchRoute(path);
        if (route) {
            this.executeRoute(route, 'push', state);
        } else {
            this.handle404(path);
        }
    }
    
    // 替换当前路径
    replace(path, state = {}) {
        const route = this.matchRoute(path);
        if (route) {
            this.executeRoute(route, 'replace', state);
        } else {
            this.handle404(path);
        }
    }
    
    // 匹配路由
    matchRoute(path) {
        // 解析路径和查询参数
        const [pathname, search] = path.split('?');
        const query = this.parseQuery(search);
        
        // 查找匹配的路由
        for (const [routePath, route] of this.routes) {
            const params = this.matchPath(pathname, routePath);
            if (params !== null) {
                return {
                    ...route,
                    params: params,
                    query: query,
                    fullPath: path,
                    pathname: pathname
                };
            }
        }
        
        return null;
    }
    
    // 路径匹配
    matchPath(pathname, routePath) {
        // 简单的路径匹配实现
        const pathParts = pathname.split('/').filter(part => part);
        const routeParts = routePath.split('/').filter(part => part);
        
        if (pathParts.length !== routeParts.length) {
            return null;
        }
        
        const params = {};
        
        for (let i = 0; i < routeParts.length; i++) {
            const routePart = routeParts[i];
            const pathPart = pathParts[i];
            
            if (routePart.startsWith(':')) {
                // 动态参数
                const paramName = routePart.slice(1);
                params[paramName] = decodeURIComponent(pathPart);
            } else if (routePart !== pathPart) {
                // 静态路径不匹配
                return null;
            }
        }
        
        return params;
    }
    
    // 解析查询参数
    parseQuery(search) {
        if (!search) return {};
        
        const params = new URLSearchParams(search);
        const query = {};
        
        for (const [key, value] of params) {
            if (query[key]) {
                if (Array.isArray(query[key])) {
                    query[key].push(value);
                } else {
                    query[key] = [query[key], value];
                }
            } else {
                query[key] = value;
            }
        }
        
        return query;
    }
    
    // 执行路由
    async executeRoute(route, action = 'push', state = {}) {
        try {
            // 执行中间件
            for (const middleware of this.middlewares) {
                const result = await middleware(route, this.currentRoute);
                if (result === false) {
                    return; // 中间件阻止导航
                }
            }
            
            // 更新历史记录
            const fullState = {
                route: route.path,
                params: route.params,
                query: route.query,
                ...state
            };
            
            if (action === 'push') {
                history.pushState(fullState, '', route.fullPath);
            } else if (action === 'replace') {
                history.replaceState(fullState, '', route.fullPath);
            }
            
            // 执行路由处理器
            await route.handler(route);
            
            // 更新当前路由
            this.currentRoute = route;
            
            // 触发路由变化事件
            this.dispatchRouteChange(route, action);
            
        } catch (error) {
            console.error('路由执行失败:', error);
            this.handleError(error, route);
        }
    }
    
    // 处理404
    handle404(path) {
        const notFoundRoute = this.routes.get('*') || this.routes.get('/404');
        if (notFoundRoute) {
            this.executeRoute({
                ...notFoundRoute,
                params: { path },
                query: {},
                fullPath: path,
                pathname: path
            });
        } else {
            console.error('404: 页面未找到:', path);
        }
    }
    
    // 处理错误
    handleError(error, route) {
        const errorRoute = this.routes.get('/error');
        if (errorRoute) {
            this.executeRoute({
                ...errorRoute,
                params: { error: error.message },
                query: {},
                fullPath: '/error',
                pathname: '/error'
            });
        }
    }
    
    // 设置事件监听器
    setupEventListeners() {
        // 监听popstate事件
        window.addEventListener('popstate', (event) => {
            this.handlePopState(event);
        });
        
        // 拦截链接点击
        document.addEventListener('click', (event) => {
            this.handleLinkClick(event);
        });
    }
    
    // 处理popstate事件
    handlePopState(event) {
        const state = event.state;
        const path = location.pathname + location.search;
        
        const route = this.matchRoute(path);
        if (route) {
            this.executeRoute(route, 'pop', state);
        }
    }
    
    // 处理链接点击
    handleLinkClick(event) {
        const link = event.target.closest('a');
        if (!link) return;
        
        const href = link.getAttribute('href');
        if (!href || href.startsWith('http') || href.startsWith('mailto:')) {
            return; // 外部链接或邮件链接
        }
        
        event.preventDefault();
        this.push(href);
    }
    
    // 处理初始路由
    handleInitialRoute() {
        const path = location.pathname + location.search;
        const route = this.matchRoute(path);
        
        if (route) {
            this.executeRoute(route, 'replace');
        } else {
            this.handle404(path);
        }
    }
    
    // 触发路由变化事件
    dispatchRouteChange(route, action) {
        const event = new CustomEvent('routechange', {
            detail: {
                route: route,
                action: action,
                timestamp: Date.now()
            }
        });
        
        window.dispatchEvent(event);
    }
    
    // 获取当前路由
    getCurrentRoute() {
        return this.currentRoute;
    }
    
    // 销毁路由器
    destroy() {
        window.removeEventListener('popstate', this.handlePopState);
        document.removeEventListener('click', this.handleLinkClick);
        this.routes.clear();
        this.middlewares = [];
        this.currentRoute = null;
    }
}

// 使用SPA路由系统
const router = new SPARouter();

// 注册中间件
router.use(async (to, from) => {
    console.log(`导航: ${from?.path || '/'} -> ${to.path}`);
    
    // 权限检查示例
    if (to.path.startsWith('/admin') && !checkUserPermission()) {
        router.push('/login');
        return false; // 阻止导航
    }
    
    return true;
});

// 注册路由
router
    .route('/', async (route) => {
        document.getElementById('app').innerHTML = '<h1>首页</h1>';
    })
    .route('/about', async (route) => {
        document.getElementById('app').innerHTML = '<h1>关于我们</h1>';
    })
    .route('/user/:id', async (route) => {
        const userId = route.params.id;
        document.getElementById('app').innerHTML = `<h1>用户: ${userId}</h1>`;
    })
    .route('/products', async (route) => {
        const category = route.query.category || 'all';
        document.getElementById('app').innerHTML = `<h1>产品列表 - ${category}</h1>`;
    })
    .route('*', async (route) => {
        document.getElementById('app').innerHTML = '<h1>404 - 页面未找到</h1>';
    });

// 监听路由变化
window.addEventListener('routechange', (event) => {
    console.log('路由变化:', event.detail);
});

// 权限检查函数示例
function checkUserPermission() {
    return localStorage.getItem('userToken') !== null;
}

"掌握history对象,构建现代化的单页应用路由系统!这是现代Web开发不可或缺的核心技能。"