点击指向当前路径的RouterLink时如何触发函数?
检测所有导航尝试(含当前页面导航)的解决方案
针对你遇到的「点击指向当前页面的RouterLink时无法触发导航监听,导致下拉菜单无法关闭」的问题,以下是几种无需逐个给RouterLink加监听的可行方案:
方案1:重写路由跳转方法,全局捕获导航尝试
通过重写Vue Router的push和replace方法,在每次调用时触发自定义事件,不管导航是否成功跳转到新路由:
// router/index.js import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(), routes: [/* 你的路由配置 */] }) // 保存原始跳转方法 const originalPush = router.push const originalReplace = router.replace // 重写push,触发自定义事件 router.push = function(location, onComplete, onAbort) { window.dispatchEvent(new CustomEvent('navigation-attempt')) return originalPush.call(this, location, onComplete, onAbort) } // 重写replace,触发自定义事件 router.replace = function(location, onComplete, onAbort) { window.dispatchEvent(new CustomEvent('navigation-attempt')) return originalReplace.call(this, location, onComplete, onAbort) } export default router
在下拉菜单组件中监听该事件,触发关闭逻辑:
// DropdownMenu.vue import { onMounted, onUnmounted, ref } from 'vue' export default { setup() { const isMenuOpen = ref(true) const closeMenuOnNavigation = () => { isMenuOpen.value = false } onMounted(() => { window.addEventListener('navigation-attempt', closeMenuOnNavigation) }) onUnmounted(() => { window.removeEventListener('navigation-attempt', closeMenuOnNavigation) }) return { isMenuOpen } } }
方案2:全局监听RouterLink点击事件
通过自定义指令给所有RouterLink绑定点击监听,统一触发菜单关闭逻辑:
// main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) // 定义全局指令,监听点击 app.directive('router-link-click', { mounted(el) { el.addEventListener('click', () => { window.dispatchEvent(new CustomEvent('navigation-attempt')) }) } }) // 给RouterLink自动应用该指令 const OriginalRouterLink = app.component('RouterLink') app.component('RouterLink', { extends: OriginalRouterLink, directives: { 'router-link-click': {} } }) app.use(router).mount('#app')
菜单组件的监听逻辑和方案1一致,无需额外修改。
方案3:强制触发导航守卫
给所有RouterLink默认添加force属性,强制触发导航守卫(即使是当前路由),再在守卫中处理菜单关闭:
// main.js import { createApp } from 'vue' import App from './App.vue' import router from './router' const app = createApp(App) // 重写RouterLink,默认开启force属性 const OriginalRouterLink = app.component('RouterLink') app.component('RouterLink', { extends: OriginalRouterLink, props: { force: { type: Boolean, default: true } } }) // 在导航守卫中触发菜单关闭 router.beforeEach(() => { window.dispatchEvent(new CustomEvent('navigation-attempt')) return true }) app.use(router).mount('#app')
菜单组件同样通过监听navigation-attempt事件关闭菜单。
内容的提问来源于stack exchange,提问作者akopyl
相关产品推荐
相关产品推荐

