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

Nuxt 3 路由切换后Modal组件Prop更新异常问题

问题:路由切换返回后,Prop控制的Modal无法再次显示

我开发了一个通过Prop控制显示的Modal组件,组件可触发close事件。正常使用时一切正常,但切换页面路由后返回承载该Modal的页面,即便Vue DevTools显示Prop值已更新,Modal也无法再次显示。

页面中Modal的使用代码

<script setup>
const subgroupModal = ref(false);

const toggleModal = () => {
  subgroupModal.value = !subgroupModal.value;
};

const closeModal = () => {
  subgroupModal.value = false;
};
</script>

<template>
  <button @click="toggleModal">
    <el-icon :size="30">
      <el-icon-circle-plus-filled class="relative text-orange top-[1px]" />
    </el-icon>
  </button>

  <ContentModal @close-modal="closeModal" :modalActive="subgroupModal">
    modal content
  </ContentModal>
</template>

Modal组件代码

<script setup>
const props = defineProps({
  modalActive: {
    type: Boolean,
    required: true
  }
});

const emit = defineEmits(['closeModal']);
const close = () => {
  emit('closeModal');
};
</script>

<template>
  <Teleport to="body">
    <Transition
      enter-from-class="opacity-0"
      leave-to-class="opacity-0"
      enter-active-class="transition duration-300"
      leave-active-class="transition duration-300"
    >
      <div
        v-if="modalActive"
        class="fixed z-50 flex items-start justify-center w-full h-full bg-black bg-opacity-60"
      >
        <div
          class="flex bg-white flex-col absolute top-[10%] md:top-[20%] sm:max-w-[1160px] w-[calc(100%-2.25rem)] pb-8 md:pb-12"
        >
          <div class="flex justify-end pt-3 pr-3 mb-3 md:mb-8">
            <button type="button" @click="close">
              <el-icon :size="55">
                <el-icon-close-bold class="text-orange" />
              </el-icon>
            </button>
          </div>
          <slot></slot>
        </div>
      </div>
    </Transition>
  </Teleport>
</template>
解决方案

核心原因

问题出在Teleport组件的DOM管理上:路由切换时,承载Modal的页面组件被卸载,但Teleport到body的Modal DOM可能未被正确清理;或者重新挂载后,Transition组件的状态没有重置,导致无法响应modalActive的变化。

方法1:给Teleport添加唯一Key

给Teleport绑定与路由关联的唯一key,确保路由切换后Teleport重新渲染,清理旧DOM并创建新实例:

<!-- 修改Modal组件的Teleport部分 -->
<Teleport to="body" :key="$route.fullPath">
  <!-- 原Transition和Modal内容 -->
</Teleport>

需要在Modal组件中引入路由实例:

<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
// 原props和emit代码
</script>

方法2:用v-show替代v-if(配合Transition的appear属性)

将Modal外层的v-if改为v-show,同时给Transition添加appear属性,确保初始渲染时触发过渡效果:

<Transition
  appear
  enter-from-class="opacity-0"
  leave-to-class="opacity-0"
  enter-active-class="transition duration-300"
  leave-active-class="transition duration-300"
>
  <div
    v-show="modalActive"
    class="fixed z-50 flex items-start justify-center w-full h-full bg-black bg-opacity-60"
  >
    <!-- 原Modal内容 -->
  </div>
</Transition>

v-show仅控制元素显示隐藏,DOM始终存在,避免了v-if卸载DOM导致的Teleport残留问题,路由返回后能正确响应prop变化。

方法3:页面卸载时重置Modal状态

在承载Modal的页面组件中,通过onUnmounted钩子重置控制变量,确保路由返回时状态初始化为false:

<script setup>
import { ref, onUnmounted } from 'vue';

const subgroupModal = ref(false);

const toggleModal = () => {
  subgroupModal.value = !subgroupModal.value;
};

const closeModal = () => {
  subgroupModal.value = false;
};

onUnmounted(() => {
  subgroupModal.value = false;
});
</script>

该方法可配合前两种方法使用,避免残留状态影响下次页面渲染。

内容的提问来源于stack exchange,提问作者MonTOne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:17:08