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

使用unplugin-vue-router实现带路由参数的模态对话框

用unplugin-vue-router实现带独立URL的模态弹窗

完全可以用unplugin-vue-router实现这个需求,核心是利用嵌套路由+路由参数,把弹窗作为子路由挂载在列表页面的父路由下,既支持点击列表项触发弹窗并更新URL,也支持直接访问详情URL时自动弹出弹窗并保留后方的列表页面。以下是具体实现步骤:

1. 路由结构设计

不管用unplugin-vue-router的文件系统路由还是手动配置路由,都要遵循嵌套结构:

  • 父路由:/servers,负责渲染服务器列表
  • 子路由:/servers/:id,负责渲染对应ID的服务器详情弹窗

方式一:文件系统路由(推荐,unplugin-vue-router原生支持)

按照如下目录结构创建文件,unplugin-vue-router会自动生成路由:

src/pages/
├── servers/
│   ├── index.vue       # 父路由:服务器列表页面
│   └── [id].vue        # 子路由:服务器详情弹窗
└── ...

方式二:手动配置路由

如果需要自定义路由名称或元信息,可以在router.ts中手动配置:

import { createRouter, createWebHistory } from 'vue-router'
import { routes } from 'vue-router/auto-routes'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    ...routes,
    {
      path: '/servers',
      name: 'servers',
      component: () => import('./pages/servers/index.vue'),
      children: [
        {
          path: ':id',
          name: 'server-detail',
          component: () => import('./pages/servers/[id].vue'),
          meta: { isModal: true } // 标记为弹窗路由,方便后续处理
        }
      ]
    }
  ]
})

export default router

2. 实现服务器列表组件(servers/index.vue)

这个组件负责渲染列表,点击项时跳转到子路由触发弹窗:

<template>
  <div class="server-list">
    <h1>服务器列表</h1>
    <div v-for="server in servers" :key="server.id" class="server-item" @click="openDetail(server.id)">
      {{ server.name }} - {{ server.status }}
    </div>
    <!-- 子路由出口:弹窗会渲染在这里 -->
    <router-view />
  </div>
</template>

<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()

// 模拟服务器数据
const servers = [
  { id: '1', name: '服务器A', status: '运行中' },
  { id: '2', name: '服务器B', status: '维护中' }
]

const openDetail = (id) => {
  router.push({ name: 'servers-[id]', params: { id } }) // 文件系统路由自动生成的名称,手动配置的话用'server-detail'
}
</script>

<style scoped>
.server-list {
  padding: 20px;
}
.server-item {
  padding: 10px;
  border: 1px solid #eee;
  margin: 10px 0;
  cursor: pointer;
}
.server-item:hover {
  background: #f5f5f5;
}
</style>

3. 实现弹窗详情组件(servers/[id].vue)

这个组件作为子路由,负责渲染弹窗、加载详情,以及关闭弹窗时的路由处理:

<template>
  <!-- 弹窗遮罩层 -->
  <div class="modal-overlay" @click="closeModal">
    <!-- 弹窗内容区,点击内部不触发关闭 -->
    <div class="modal-content" @click.stop>
      <button class="close-btn" @click="closeModal">×</button>
      <h2>服务器详情</h2>
      <p>ID: {{ serverId }}</p>
      <p>名称: {{ server?.name }}</p>
      <p>状态: {{ server?.status }}</p>
    </div>
  </div>
</template>

<script setup>
import { useRouter, useRoute } from 'vue-router'
import { ref, onMounted, watch } from 'vue'

const router = useRouter()
const route = useRoute()
const serverId = ref(route.params.id)
const server = ref(null)

// 模拟根据ID获取服务器详情
const fetchServerDetail = async (id) => {
  // 这里替换成真实的API请求
  await new Promise(resolve => setTimeout(resolve, 300))
  const mockData = [
    { id: '1', name: '服务器A', status: '运行中', ip: '192.168.1.100' },
    { id: '2', name: '服务器B', status: '维护中', ip: '192.168.1.101' }
  ]
  server.value = mockData.find(item => item.id === id)
}

onMounted(() => {
  fetchServerDetail(serverId.value)
})

// 监听路由参数变化,更新详情
watch(() => route.params.id, (newId) => {
  serverId.value = newId
  fetchServerDetail(newId)
})

const closeModal = () => {
  router.back() // 回退到父路由,或者用router.push('/servers')
}
</script>

<style scoped>
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  width: 400px;
  position: relative;
}

.close-btn {
  position: absolute;
  top: 10px;
  right: 15px;
  border: none;
  background: transparent;
  font-size: 20px;
  cursor: pointer;
}
</style>

4. 关键逻辑说明

  • 路由嵌套:父路由/servers始终渲染列表,子路由/servers/:id渲染弹窗,直接访问子路由时,父路由会先加载,再渲染弹窗,满足“弹窗后方显示列表”的需求。
  • 路由参数监听:弹窗组件监听route.params.id的变化,切换不同服务器时自动更新详情。
  • 弹窗关闭处理:点击关闭按钮或遮罩层时,通过router.back()回退到父路由,URL也会同步回到/servers。
  • 无依赖弹窗:完全自定义CSS实现弹窗,不需要Vuetify等UI库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:16:11