You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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>

问题原因

  1. Nuxt会缓存已渲染的页面,返回缓存页面时不会重新执行初始化阶段的calcMenu(),导致showMenu停留在之前跳转页面时的状态,未根据当前窗口宽度重新计算
  2. 当前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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 09:35:19