在JavaScript中如何用浏览器原生API监听单页应用的路径变化?
可以通过浏览器原生API实现,核心原因是你之前用到的
onpopstate仅会在浏览器前进/后退、调用history.go()/history.back()/history.forward()时触发,而SPA路由切换常用的history.pushState()、history.replaceState()调用时不会触发该事件,所以才会不符合需求。 实现步骤
- 重写
history.pushState和history.replaceState原生方法,在方法执行完成后抛出自定义事件,捕获主动修改路由的行为 - 监听
popstate事件覆盖浏览器前进后退的路由变化场景 - 监听
DOMContentLoaded事件处理页面首次加载的回调触发需求
完整实现代码
// 注册自定义路由变化事件 const createRouteChangeEvent = (eventName) => { const originalMethod = history[eventName] return function() { const returnValue = originalMethod.apply(this, arguments) const event = new Event(eventName.toLowerCase()) window.dispatchEvent(event) // 同时触发统一的routechange事件 window.dispatchEvent(new CustomEvent('routechange', { detail: { path: window.location.pathname + window.location.search + window.location.hash } })) return returnValue } } // 重写两个修改路由的核心方法 history.pushState = createRouteChangeEvent('pushState') history.replaceState = createRouteChangeEvent('replaceState') // 绑定路由变化监听 const addRouteChangeListener = (callback) => { // 首次加载直接执行回调 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { callback(window.location.pathname + window.location.search + window.location.hash) }) } else { callback(window.location.pathname + window.location.search + window.location.hash) } // 监听三种路由变化场景 window.addEventListener('pushstate', () => callback(window.location.pathname + window.location.search + window.location.hash)) window.addEventListener('replacestate', () => callback(window.location.pathname + window.location.search + window.location.hash)) window.addEventListener('popstate', () => callback(window.location.pathname + window.location.search + window.location.hash)) }
使用示例
// 传入你要执行的指定函数即可 addRouteChangeListener((currentPath) => { console.log('路由发生变化,当前路径:', currentPath) // 在这里执行你对应页面的业务逻辑 })
注意事项
- 该实现不会污染原生路由的行为,所有原生
history方法的功能都可以正常使用 - 如果需要移除监听,可以自行存储绑定的回调函数,调用
removeEventListener移除对应事件即可
内容的提问来源于stack exchange,提问作者Tamil Vendhan Kanagarasu
相关产品推荐
相关产品推荐

