Nuxt响应式菜单返回已渲染页面时无法正确加载的问题
响应式菜单返回已渲染页面时无法正常显示的问题
需求说明
- 桌面端(≥1024px)菜单始终以行布局展示,
showMenu变量需保持为true - 移动端(<1024px)菜单以列布局展示,仅当
showMenu为true时显示
当前脚本代码
const showMenu = ref(true); if (process.client) { calcMenu(); window.addEventListener('resize', () => { calcMenu(); }); } function calcMenu() { const width = window.innerWidth; if (width < 1024) { showMenu.value = false; } }
问题表现
首次访问网站、跳转新页面时菜单均正常工作;但返回已渲染过的页面时,菜单无法正常显示,必须点击菜单按钮或刷新页面才能恢复。
异常菜单展示

正常菜单展示

当前模板代码
<template> <div class=""> <div class="flex justify-between text-secondary flex-col bg-primary lg:flex-row fixed left-0 right-0 top-0 z-50"> <div class="flex flex-row items-center justify-between"> <nuxt-link to="/" @click="() => { showMenu = false }" class="m-4 lg:invisible" > <img src="/logo.png" alt="Magruders Logo" class="h-20 w-20" v-if="!showMenu"> </nuxt-link> <button v-if="!showMenu" @click="() => { showMenu = true }" class="btn inverse">Menu</button> </div> <ul v-if="showMenu" class="flex flex-col lg:flex-row text-center justify-between w-full"> <nuxt-link to="/" @click="() => { showMenu = false }" class="m-auto lg:m-4 lg:visible lg:h-20 lg:w-20 invisible h-0 w-0"> <img src="/logo.png" alt="Magruders Logo"> </nuxt-link> <div class="flex flex-col lg:flex-row lg:h-20 items-center self-center"> <button v-if="showMenu" @click="() => { showMenu = false }" class="btn inverse lg:invisible p-0">Close</button> <nuxt-link to="/" @click="() => { showMenu = false }" class="m-auto lg:m-4 lg:invisible"> <img src="/logo.png" alt="Magruders Logo" class="h-20 w-20"> </nuxt-link> <li class="btn inverse"> <nuxt-link to="/" @click="() => { showMenu = false }">Home</nuxt-link> </li> <li class="btn inverse"> <nuxt-link to="/funerals" @click="() => { showMenu = false }">Funerals</nuxt-link> </li> <li class="btn inverse"> <nuxt-link to="/banquets" @click="() => { showMenu = false }">Banquets</nuxt-link> </li> <li class="btn inverse"> <nuxt-link to="/pub" @click="() => { showMenu = false }">Pub</nuxt-link> </li> </div> </ul> </div> <div class="text-black p-4 pt-24 m-4 flex flex-col items-center text-center"> <slot /> </div> </div> </template>
问题原因
- Nuxt会缓存已渲染的页面,返回缓存页面时不会重新执行初始化阶段的
calcMenu(),导致showMenu停留在之前跳转页面时的状态,未根据当前窗口宽度重新计算 - 当前
calcMenu()仅处理了移动端设为false的情况,桌面端未明确强制设置showMenu为true,若之前状态为false,返回桌面端页面时无法自动恢复
解决方案
1. 完善calcMenu()逻辑
明确区分桌面端和移动端的showMenu状态:
function calcMenu() { const width = window.innerWidth; // 桌面端强制true,移动端强制false showMenu.value = width >= 1024; }
2. 页面激活时重新计算菜单状态
利用Nuxt的onActivated钩子,在页面从缓存恢复时重新执行状态计算,同时添加监听清理避免内存泄漏:
const showMenu = ref(true); if (process.client) { calcMenu(); window.addEventListener('resize', calcMenu); } // 页面从缓存激活时重新计算 onActivated(() => { if (process.client) { calcMenu(); } }); function calcMenu() { const width = window.innerWidth; showMenu.value = width >= 1024; } // 页面卸载时移除监听 onUnmounted(() => { if (process.client) { window.removeEventListener('resize', calcMenu); } });
3. 模板逻辑优化(可选)
简化模板中重复的nuxt-link和按钮逻辑,减少状态冲突点,比如统一桌面端菜单的显示逻辑,避免额外的showMenu判断干扰。
内容的提问来源于stack exchange,提问作者Jacob Miller
相关产品推荐
相关产品推荐

