Nuxt.js单页应用菜单高亮脚本路由导航时失效求助
问题分析
直接访问页面时代码生效是因为页面会完整加载,代码执行一次;但SPA路由跳转是客户端无刷新切换,原代码仅在页面首次加载时运行,路由切换后不会重新触发,所以菜单高亮失效。即使切换到Universal模式,客户端路由跳转时也不会重新执行初始加载的代码,因此问题无法解决。
解决方案
推荐三种可行方案,按优雅度排序:
方案1:响应式动态绑定(最推荐)
无需手动操作DOM,利用Nuxt的路由响应式特性直接绑定状态:
<template> <nav> <a class="accueil" href="/" :id="route.path === '/' ? 'active' : null" >Accueil</a> <a class="tous-les-articles" href="/tous-les-articles" :id="route.path === '/tous-les-articles' ? 'active' : null" >Tous les articles</a> <a class="sciences" href="/sciences" :id="route.path === '/sciences' ? 'active' : null" >Sciences</a> <a class="actualites" href="/actualites" :id="route.path === '/actualites' ? 'active' : null" >Actualités</a> <a class="histoire" href="/histoire" :id="route.path === '/histoire' ? 'active' : null" >Histoire</a> <a class="livres" href="/livres" :id="route.path === '/livres' ? 'active' : null" >Livres</a> <a class="le-saviez-vous" href="/le-saviez-vous" :id="route.path === '/le-saviez-vous' ? 'active' : null" >Le saviez-vous?</a> </nav> <nuxt /> </template> <script setup> import { useRoute } from 'vue-router'; const route = useRoute(); </script>
路由切换时,route.path会自动更新,绑定的id也会同步变化,完全符合Vue响应式逻辑。
方案2:布局组件监听路由变化
在全局布局文件(如layouts/default.vue)中监听路由切换,触发菜单状态更新:
<template> <nav> <!-- 菜单结构保持不变 --> <a class="accueil" href="/">Accueil</a> <a class="tous-les-articles" href="/tous-les-articles">Tous les articles</a> <!-- 其他菜单项 --> </nav> <nuxt /> </template> <script setup> import { watch, onMounted } from 'vue'; import { useRoute } from 'vue-router'; const route = useRoute(); const updateActiveMenu = () => { // 先清除所有已激活的菜单id document.querySelectorAll('#active').forEach(el => el.removeAttribute('id')); // 路由路径与菜单类名映射 const pathMap = { '/': 'accueil', '/tous-les-articles': 'tous-les-articles', '/sciences': 'sciences', '/actualites': 'actualites', '/histoire': 'histoire', '/livres': 'livres', '/le-saviez-vous': 'le-saviez-vous' }; const targetClass = pathMap[route.path]; if (targetClass) { const menuItem = document.querySelector(`.${targetClass}`); if (menuItem) menuItem.setAttribute('id', 'active'); } }; // 页面首次加载时执行 onMounted(updateActiveMenu); // 监听路由变化,每次切换都更新 watch(() => route.path, updateActiveMenu); </script>
方案3:全局路由中间件
创建全局中间件,每次路由切换时执行菜单更新逻辑:
- 在项目根目录创建
middleware/activeMenu.js:
export default function ({ route }) { // 确保仅在客户端执行(服务端无DOM) if (process.client) { // 清除所有激活状态 document.querySelectorAll('#active').forEach(el => el.removeAttribute('id')); const pathMap = { '/': 'accueil', '/tous-les-articles': 'tous-les-articles', '/sciences': 'sciences', '/actualites': 'actualites', '/histoire': 'histoire', '/livres': 'livres', '/le-saviez-vous': 'le-saviez-vous' }; const targetClass = pathMap[route.path]; if (targetClass) { const menuItem = document.querySelector(`.${targetClass}`); if (menuItem) menuItem.setAttribute('id', 'active'); } } }
- 在
nuxt.config.js中注册全局中间件:
export default { router: { middleware: ['activeMenu'] } }
内容的提问来源于stack exchange,提问作者MH info
相关产品推荐
相关产品推荐

