前端核心框架vue之(路由核心案例篇3/5) - 指南

写在前面的话:这是一个综合的案例,涉及到守卫,重定向。入门初级的兄弟们可以逐个技术栈速通,不要沉迷知识点的学习过程,实操可能更加的重要主包写了两三天

建议用时(2天-5天)

Vue CLI 路由专项训练_前端开发文档

项目目标

开发一个具有完整前端路由功能的单页应用,涵盖权限控制、路由跳转、动态嵌套路由、查询参数、懒加载、重定向与 404 页面处理,用于 Vue Router 的专项训练。

技术要求

  • Vue 2.x
  • Vue Router 3.x
  • Vue CLI 构建
  • Element UI 用于页面 UI
  • 项目目录结构清晰、组件模块划分合理

项目结构建议

src/
├── main.js
├── router/
│   ├── index.js          // 路由配置
│   └── guards.js         // 路由守卫
├── views/
│   ├── Home.vue
│   ├── About.vue
│   ├── Products.vue
│   ├── Dashboard.vue
│   ├── Admin.vue
│   ├── RedirectInfo.vue
│   ├── NotFound.vue
│   └── user/
│       ├── UserDetail.vue
│       ├── UserProfile.vue
│       └── UserSettings.vue
└── App.vue

路由功能要求

✅ 基础页面

  • / 首页
  • /about 关于页面
  • 页面中按钮跳转需通过路由控制

路由权限控制

  • /dashboard:登录后才能访问
  • /admin:仅管理员才能访问
  • 配置路由元信息 meta.requiresAuth / meta.requiresAdmin

动态 & 嵌套路由

  • /user/:id:用户详情页
  • 嵌套:/user/:id/profile/user/:id/settings
  • 子页面通过 <router-view> 展示

查询参数

  • /products?category=xxx&page=1
  • 页面应能读取并展示查询条件

懒加载路由

  • /lazy:以异步组件形式加载页面
  • 页面应模拟加载延迟(2秒左右)

重定向

  • /redirect-test/about
  • /old-dashboard/dashboard

404 页面

  • 无匹配路径 → 显示 NotFound 页面

总览:

模块要求说明
基础路由配置所有页面路径与组件绑定正确
页面跳转页面内跳转通过 $router 实现
动态路由能读取用户 ID 并展示相关内容
嵌套路由子页面通过嵌套路由显示
查询参数处理页面可读写查询参数,刷新保持状态
路由守卫登录/权限控制逻辑合理,跳转提示完整
懒加载实现页面实现异步加载逻辑并显示加载提示
重定向与 404能正常重定向,404 页面显示无误
路由导航栏高亮状态导航菜单可识别当前路由状态

这里是参考答案,直接运行单个HTML文件即可

<!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Vue Router 核心功能训练 - 修复版</title>
          <!-- Element Plus CSS -->
              <link rel="stylesheet" href="https://unpkg.com/element-plus@2.4.4/dist/index.css">
              <!-- Vue 3 -->
              <script src="https://unpkg.com/vue@3.3.8/dist/vue.global.js"></script>
                <!-- Vue Router 4 -->
                <script src="https://unpkg.com/vue-router@4.2.5/dist/vue-router.global.js"></script>
                  <!-- Element Plus -->
                  <script src="https://unpkg.com/element-plus@2.4.4/dist/index.full.js"></script>
                    <!-- Element Plus Icons -->
                    <script src="https://unpkg.com/@element-plus/icons-vue@2.1.0/dist/index.iife.min.js"></script>
                    </head>
                    <body>
                    <div id="app"></div>
                      <script>
                        const { createApp, ref, reactive, computed } = Vue;
                        const { createRouter, createWebHashHistory } = VueRouter;
                        const { ElMessage, ElMessageBox } = ElementPlus;
                        // 权限状态管理 - 修复响应式问题
                        const authState = reactive({
                        isLoggedIn: false,  // 直接使用普通值,不需要ref
                        isAdmin: false,     // 直接使用普通值,不需要ref  
                        username: '',       // 直接使用普通值,不需要ref
                        async login() {
                        try {
                        // 模拟登录过程
                        const { value: credentials } = await ElMessageBox.prompt('请输入用户名 (admin/user)', '登录', {
                        confirmButtonText: '登录',
                        cancelButtonText: '取消',
                        inputPattern: /\S+/,
                        inputErrorMessage: '用户名不能为空'
                        });
                        // 预设账号逻辑
                        if (credentials === 'admin') {
                        this.isLoggedIn = true;
                        this.isAdmin = true;
                        this.username = 'admin';
                        ElMessage.success(' 管理员登录成功!');
                        } else if (credentials === 'user') {
                        this.isLoggedIn = true;
                        this.isAdmin = false;
                        this.username = 'user';
                        ElMessage.success('✅ 普通用户登录成功!');
                        } else {
                        // 其他用户名默认为普通用户
                        this.isLoggedIn = true;
                        this.isAdmin = false;
                        this.username = credentials;
                        ElMessage.success(`✅ 用户 ${credentials} 登录成功!`);
                        }
                        console.log('登录状态已更新 - 登录:', this.isLoggedIn, '管理员:', this.isAdmin, '用户名:', this.username);
                        } catch {
                        ElMessage.info('取消登录');
                        }
                        },
                        logout() {
                        console.log('开始退出登录...');
                        this.isLoggedIn = false;
                        this.isAdmin = false;
                        this.username = '';
                        ElMessage.success('退出登录成功');
                        console.log('退出登录完成 - 登录:', this.isLoggedIn, '管理员:', this.isAdmin, '用户名:', this.username);
                        },
                        setAdmin() {
                        console.log('尝试设为管理员 - 当前登录状态:', this.isLoggedIn, '用户名:', this.username);
                        if (!this.isLoggedIn) {
                        ElMessage.warning('请先登录');
                        return;
                        }
                        this.isAdmin = true;
                        ElMessage.success(`${this.username} 已设置为管理员`);
                        console.log('设为管理员完成 - 管理员状态:', this.isAdmin);
                        },
                        setUser() {
                        console.log('尝试设为普通用户 - 当前登录状态:', this.isLoggedIn, '用户名:', this.username);
                        if (!this.isLoggedIn) {
                        ElMessage.warning('请先登录');
                        return;
                        }
                        this.isAdmin = false;
                        ElMessage.success(`${this.username} 已设置为普通用户`);
                        console.log('设为普通用户完成 - 管理员状态:', this.isAdmin);
                        },
                        getStatusText() {
                        if (!this.isLoggedIn) return '未登录';
                        const role = this.isAdmin ? '管理员' : '普通用户';
                        return `${this.username} (${role})`;
                        }
                        });
                        // 用户设置数据(持久化)
                        const userSettings = reactive({
                        data: {},
                        save(userId, settings) {
                        this.data[userId] = { ...settings };
                        ElMessage.success('设置保存成功');
                        },
                        load(userId) {
                        return this.data[userId] || {
                        emailNotify: true,
                        smsNotify: false,
                        privacy: 'public'
                        };
                        }
                        });
                        // 路由组件
                        // 首页
                        const Home = {
                        template: `
                        <div>
                          <el-alert title="Vue Router 核心功能训练 - 修复版" type="success" show-icon />
                          <!-- 权限控制面板 -->
                            <el-card style="margin-top: 20px;">
                              <template #header>
                              <span>权限控制面板 - 路由守卫测试</span>
                              </template>
                              <!-- 添加账号说明 -->
                                <el-alert
                                title="测试账号说明"
                                type="info"
                                :closable="false"
                                style="margin-bottom: 15px;"
                                >
                              <p><strong>管理员账号:</strong> admin</p>
                              <p><strong>普通用户:</strong> user</p>
                              <p><strong>其他用户名:</strong> 默认为普通用户</p>
                              </el-alert>
                              <div style="margin-bottom: 15px;">
                              当前状态: <el-tag :type="getTagType()">{{ authState.getStatusText() }}</el-tag>
                              </div>
                              <el-space>
                                <el-button @click="handleLogin" type="success" :disabled="authState.isLoggedIn">
                                <el-icon><User /></el-icon>
                                登录
                              </el-button>
                              <el-button @click="handleLogout" type="info" :disabled="!authState.isLoggedIn">
                              <el-icon><SwitchButton /></el-icon>
                              退出登录
                            </el-button>
                            <el-button @click="handleSetAdmin" type="danger" :disabled="authState.isAdmin || !authState.isLoggedIn">
                            <el-icon><Crown /></el-icon>
                            设为管理员
                          </el-button>
                          <el-button @click="handleSetUser" type="warning" :disabled="!authState.isAdmin">
                          <el-icon><Avatar /></el-icon>
                          设为普通用户
                        </el-button>
                      </el-space>
                    </el-card>
                    <el-row :gutter="20" style="margin-top: 20px;">
                      <el-col :span="12">
                        <el-card header="基础路由">
                          <el-button @click="$router.push('/about')" block>
                          <el-icon><InfoFilled /></el-icon>
                          关于页面
                        </el-button>
                      </el-card>
                    </el-col>
                    <el-col :span="12">
                      <el-card header="动态路由">
                        <el-button @click="$router.push('/user/123')" block>
                        <el-icon><User /></el-icon>
                        用户 123
                      </el-button>
                    </el-card>
                  </el-col>
                </el-row>
                <el-row :gutter="20" style="margin-top: 20px;">
                  <el-col :span="12">
                    <el-card header="查询参数">
                      <el-button @click="$router.push('/products?category=books')" block>
                      <el-icon><Reading /></el-icon>
                      图书分类
                    </el-button>
                  </el-card>
                </el-col>
                <el-col :span="12">
                  <el-card header="路由守卫测试">
                    <el-space direction="vertical" style="width: 100%;">
                      <el-button @click="$router.push('/dashboard')" type="primary" block>
                      <el-icon><DataBoard /></el-icon>
                      需要登录
                    </el-button>
                    <el-button @click="$router.push('/admin')" type="danger" block>
                    <el-icon><Setting /></el-icon>
                    需要管理员
                  </el-button>
                </el-space>
              </el-card>
            </el-col>
          </el-row>
          <el-row :gutter="20" style="margin-top: 20px;">
            <el-col :span="24">
              <el-card header="其他功能">
                <el-space>
                  <el-button @click="$router.push('/lazy')" type="warning">
                  <el-icon><Loading /></el-icon>
                  懒加载
                </el-button>
                <el-button @click="testRedirect" type="info">
                <el-icon><Right /></el-icon>
                重定向测试
              </el-button>
              <el-button @click="$router.push('/notfound')" type="danger">
              <el-icon><WarningFilled /></el-icon>
              404测试
            </el-button>
          </el-space>
        </el-card>
      </el-col>
    </el-row>
  </div>
  `,
  computed: {
  authState() {
  return authState;
  }
  },
  methods: {
  async handleLogin() {
  console.log('点击登录按钮');
  await authState.login();
  this.$forceUpdate(); // 强制更新组件
  },
  handleLogout() {
  console.log('点击退出登录按钮');
  authState.logout();
  this.$forceUpdate(); // 强制更新组件
  },
  handleSetAdmin() {
  console.log('点击设为管理员按钮');
  authState.setAdmin();
  this.$forceUpdate(); // 强制更新组件
  },
  handleSetUser() {
  console.log('点击设为普通用户按钮');
  authState.setUser();
  this.$forceUpdate(); // 强制更新组件
  },
  getTagType() {
  if (!authState.isLoggedIn) return 'info';
  return authState.isAdmin ? 'danger' : 'success';
  },
  testRedirect() {
  ElMessage.info('即将重定向到关于页面...');
  setTimeout(() => {
  this.$router.push('/redirect-test');
  }, 1000);
  }
  }
  };
  // 关于页面
  const About = {
  template: `
  <div>
    <el-alert title="关于页面 - 基础路由演示" type="info" show-icon />
    <el-card style="margin-top: 20px;">
    <p>这是一个基础路由页面,演示了简单的页面跳转功能。</p>
    <el-divider />
  <p><strong>路由信息:</strong></p>
    <ul>
    <li>路径: {{ $route.path }}</li>
    <li>名称: {{ $route.name || '未命名' }}</li>
    <li>来源: {{ $route.meta.from || '直接访问' }}</li>
    </ul>
    <el-space style="margin-top: 20px;">
    <el-button @click="$router.back()" icon="ArrowLeft">返回上页</el-button>
    <el-button @click="$router.push('/')" type="primary" icon="House">返回首页</el-button>
    </el-space>
  </el-card>
</div>
`
};
// 重定向说明页面
const RedirectInfo = {
template: `
<div>
  <el-alert title="重定向演示页面" type="warning" show-icon />
  <el-card style="margin-top: 20px;">
  <p> <strong>重定向逻辑说明:</strong></p>
    <ol>
    <li>当您访问 <code>/redirect-test</code> 时</li>
    <li>路由会自动重定向到 <code>/about</code> 页面</li>
    <li>但会在 about 页面的 meta 中标记来源为 "重定向"</li>
    </ol>
    <el-divider />
  <p><strong>测试重定向:</strong></p>
    <el-space direction="vertical" style="width: 100%;">
      <el-button @click="testRedirect1" type="primary" block>
        测试重定向 1: /redirect-test → /about
      </el-button>
      <el-button @click="testRedirect2" type="success" block>
        测试重定向 2: /old-dashboard → /dashboard (需要登录)
      </el-button>
      <el-button @click="testRedirect3" type="warning" block>
        测试重定向 3: /legacy-admin → /admin (需要管理员)
      </el-button>
    </el-space>
    <el-space style="margin-top: 20px;">
    <el-button @click="$router.back()" icon="ArrowLeft">返回上页</el-button>
    <el-button @click="$router.push('/')" type="primary" icon="House">返回首页</el-button>
    </el-space>
  </el-card>
</div>
`,
methods: {
testRedirect1() {
ElMessage.info('即将重定向: /redirect-test → /about');
setTimeout(() => {
this.$router.push('/redirect-test');
}, 1000);
},
testRedirect2() {
ElMessage.info('即将重定向: /old-dashboard → /dashboard');
setTimeout(() => {
this.$router.push('/old-dashboard');
}, 1000);
},
testRedirect3() {
ElMessage.info('即将重定向: /legacy-admin → /admin');
setTimeout(() => {
this.$router.push('/legacy-admin');
}, 1000);
}
}
};
// 用户详情页面 - 动态路由
const UserDetail = {
template: `
<div>
  <el-alert :title="'用户详情 - ID: ' + $route.params.id + ' (动态路由)'" type="success" show-icon />
  <el-card style="margin-top: 20px;">
  <p><strong>用户ID:</strong> {{ $route.params.id }}</p>
  <p><strong>用户名:</strong> 用户{{ $route.params.id }}</p>
  <el-divider content-position="left">嵌套路由</el-divider>
    <el-space>
      <el-button @click="$router.push('/user/' + $route.params.id + '/profile')" type="primary">
      <el-icon><User /></el-icon>
      个人资料
    </el-button>
    <el-button @click="$router.push('/user/' + $route.params.id + '/settings')" type="success">
    <el-icon><Setting /></el-icon>
    账户设置
  </el-button>
</el-space>
<!-- 嵌套路由出口 -->
  <div style="margin-top: 20px;">
  <router-view></router-view>
  </div>
  <el-divider />
  <el-space>
  <el-button @click="$router.back()" icon="ArrowLeft">返回上页</el-button>
  <el-button @click="$router.push('/')" type="primary" icon="House">返回首页</el-button>
  </el-space>
</el-card>
</div>
`
};
// 用户资料 - 嵌套路由
const UserProfile = {
template: `
<el-card>
<template #header>
<el-icon><User /></el-icon>
个人资料 (嵌套路由)
</template>
<p><strong>真实姓名:</strong> 用户{{ $route.params.id }}</p>
<p><strong>邮箱:</strong> user{{ $route.params.id }}@example.com</p>
<p><strong>注册时间:</strong> 2024-01-01</p>
<p><strong>最后登录:</strong> {{ new Date().toLocaleString() }}</p>
</el-card>
`
};
// 用户设置 - 嵌套路由
const UserSettings = {
template: `
<el-card>
<template #header>
<el-icon><Setting /></el-icon>
账户设置 (嵌套路由)
</template>
<el-form label-width="100px">
<el-form-item label="邮件通知">
<el-switch v-model="settings.emailNotify" />
</el-form-item>
<el-form-item label="短信通知">
<el-switch v-model="settings.smsNotify" />
</el-form-item>
<el-form-item label="隐私设置">
<el-select v-model="settings.privacy">
  <el-option label="公开" value="public" />
  <el-option label="仅好友" value="friends" />
  <el-option label="私密" value="private" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save">保存设置</el-button>
<el-button @click="reset">重置</el-button>
</el-form-item>
</el-form>
<el-divider />
<p><strong>当前设置:</strong></p>
<pre>{{ JSON.stringify(settings, null, 2) }}</pre>
</el-card>
`,
data() {
return {
settings: {}
};
},
created() {
this.loadSettings();
},
watch: {
'$route'() {
this.loadSettings();
}
},
methods: {
loadSettings() {
this.settings = userSettings.load(this.$route.params.id);
},
save() {
userSettings.save(this.$route.params.id, this.settings);
},
reset() {
this.settings = {
emailNotify: true,
smsNotify: false,
privacy: 'public'
};
ElMessage.info('设置已重置');
}
}
};
// 商品页面 - 查询参数
const Products = {
template: `
<div>
<el-alert title="商品列表 - 查询参数演示" type="warning" show-icon />
<el-card style="margin-top: 20px;">
<el-alert :title="'当前URL: ' + $route.fullPath" type="info" :closable="false" />
<el-form :inline="true" style="margin-top: 20px;">
<el-form-item label="分类">
  <el-select v-model="category" @change="updateQuery">
    <el-option label="全部" value="" />
    <el-option label="图书" value="books" />
    <el-option label="电子产品" value="electronics" />
    <el-option label="服装" value="clothing" />
  </el-select>
</el-form-item>
<el-form-item label="页码">
  <el-input-number v-model="page" :min="1" @change="updateQuery" />
</el-form-item>
<el-form-item>
<el-button @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<p style="margin-top: 20px;">
<strong>筛选结果:</strong>
{{ category ? '分类: ' + category : '全部商品' }}
{{ page > 1 ? ', 第' + page + '页' : '' }}
</p>
<el-space style="margin-top: 20px;">
<el-button @click="$router.back()">返回上页</el-button>
<el-button @click="$router.push('/')" type="primary">返回首页</el-button>
</el-space>
</el-card>
</div>
`,
data() {
return {
category: '',
page: 1
};
},
created() {
const query = this.$route.query;
this.category = query.category || '';
this.page = parseInt(query.page) || 1;
},
watch: {
'$route'() {
const query = this.$route.query;
this.category = query.category || '';
this.page = parseInt(query.page) || 1;
}
},
methods: {
updateQuery() {
const query = {};
if (this.category) query.category = this.category;
if (this.page > 1) query.page = this.page;
this.$router.push({ path: '/products', query: query });
},
resetQuery() {
this.$router.push('/products');
}
}
};
// 数据面板 - 需要登录
const Dashboard = {
template: `
<div>
<el-alert title="数据面板 - 路由守卫演示 (需要登录)" type="success" show-icon />
<el-card style="margin-top: 20px;">
<p> 恭喜!您已通过登录验证,可以访问此页面。</p>
<p>当前用户状态: <el-tag type="success">{{ authState.getStatusText() }}</el-tag></p>
<p>访问时间: {{ new Date().toLocaleString() }}</p>
<el-space style="margin-top: 20px;">
<el-button @click="$router.back()">返回上页</el-button>
<el-button @click="$router.push('/')" type="primary">返回首页</el-button>
</el-space>
</el-card>
</div>
`,
computed: {
authState() {
return authState;
}
}
};
// 管理员页面 - 需要管理员权限
const Admin = {
template: `
<div>
<el-alert title="管理员页面 - 路由守卫演示 (需要管理员权限)" type="danger" show-icon />
<el-card style="margin-top: 20px;">
<p> 恭喜!您拥有管理员权限,可以访问此页面。</p>
<p>当前用户状态: <el-tag type="danger">{{ authState.getStatusText() }}</el-tag></p>
<p>访问时间: {{ new Date().toLocaleString() }}</p>
<el-space style="margin-top: 20px;">
<el-button @click="$router.back()">返回上页</el-button>
<el-button @click="$router.push('/')" type="primary">返回首页</el-button>
</el-space>
</el-card>
</div>
`,
computed: {
authState() {
return authState;
}
}
};
// 懒加载页面
const LazyPage = {
template: `
<div>
<el-alert title="懒加载页面 - 异步组件演示" type="warning" show-icon />
<el-card style="margin-top: 20px;">
<p> 这个页面通过懒加载方式加载,模拟了2秒加载时间。</p>
<p>加载完成时间: {{ new Date().toLocaleString() }}</p>
<el-space style="margin-top: 20px;">
<el-button @click="$router.back()">返回上页</el-button>
<el-button @click="$router.push('/')" type="primary">返回首页</el-button>
</el-space>
</el-card>
</div>
`
};
// 404页面
const NotFound = {
template: `
<el-result
icon="warning"
title="404"
sub-title="页面未找到"
>
<template #extra>
<el-space>
<el-button @click="$router.back()">返回上页</el-button>
<el-button type="primary" @click="$router.push('/')">返回首页</el-button>
</el-space>
</template>
</el-result>
`
};
// 主应用组件
const App = {
template: `
<el-container style="min-height: 100vh;">
<!-- 头部导航 -->
<el-header>
<el-menu :default-active="$route.path" mode="horizontal">
<el-menu-item index="/" @click="$router.push('/')">
<el-icon><House /></el-icon>
首页
</el-menu-item>
<el-menu-item index="/about" @click="$router.push('/about')">
<el-icon><InfoFilled /></el-icon>
关于
</el-menu-item>
<el-menu-item index="/products" @click="$router.push('/products')">
<el-icon><Goods /></el-icon>
商品
</el-menu-item>
<el-menu-item index="/redirect-info" @click="$router.push('/redirect-info')">
<el-icon><Right /></el-icon>
重定向
</el-menu-item>
<div style="flex: 1;"></div>
<!-- 状态显示 -->
<div style="display: flex; align-items: center; margin-right: 20px;">
<span style="margin-right: 10px;">当前状态:</span>
<el-tag :type="getStatusTagType()">
{{ authState.getStatusText() }}
</el-tag>
</div>
</el-menu>
</el-header>
<!-- 主要内容 -->
<el-main>
<!-- 路由信息 -->
<el-alert
:title="getRouteInfo()"
type="info"
:closable="false"
style="margin-bottom: 20px;"
/>
<!-- 页面内容 -->
<router-view></router-view>
</el-main>
</el-container>
`,
computed: {
authState() {
return authState;
}
},
methods: {
getStatusTagType() {
if (!authState.isLoggedIn) return 'info';
return authState.isAdmin ? 'danger' : 'success';
},
getRouteInfo() {
let info = `当前路由: ${this.$route.path}`;
if (Object.keys(this.$route.params).length > 0) {
info += ` | 参数: ${JSON.stringify(this.$route.params)}`;
}
if (Object.keys(this.$route.query).length > 0) {
info += ` | 查询: ${JSON.stringify(this.$route.query)}`;
}
if (this.$route.meta.from) {
info += ` | 来源: ${this.$route.meta.from}`;
}
return info;
}
}
};
// 路由配置
const routes = [
{ path: '/', component: Home },
{
path: '/about',
component: About,
beforeEnter: (to, from, next) => {
// 检查是否来自重定向
if (from.path === '/redirect-test') {
to.meta.from = '重定向';
}
next();
}
},
{ path: '/redirect-info', component: RedirectInfo },
{
path: '/user/:id',
component: UserDetail,
children: [
{ path: 'profile', component: UserProfile },
{ path: 'settings', component: UserSettings }
]
},
{ path: '/products', component: Products },
{ path: '/dashboard', component: Dashboard, meta: { requiresAuth: true } },
{ path: '/admin', component: Admin, meta: { requiresAuth: true, requiresAdmin: true } },
{
path: '/lazy',
component: () => {
return new Promise(resolve => {
ElMessage.info('正在加载页面,请稍候...');
setTimeout(() => resolve(LazyPage), 2000);
});
}
},
// 重定向路由 - 更明显的重定向逻辑
{
path: '/redirect-test',
redirect: to => {
ElMessage.success('重定向成功: /redirect-test → /about');
return '/about';
}
},
{
path: '/old-dashboard',
redirect: '/dashboard'
},
{
path: '/legacy-admin',
redirect: '/admin'
},
{ path: '/:pathMatch(.*)*', component: NotFound }
];
// 创建路由
const router = createRouter({
history: createWebHashHistory(),
routes
});
// 路由守卫 - 改进的守卫逻辑
router.beforeEach((to, from, next) => {
console.log('=== 路由守卫检查 ===');
console.log('从:', from.path, '到:', to.path);
console.log('登录状态:', authState.isLoggedIn);
console.log('管理员状态:', authState.isAdmin);
console.log('路由元信息:', to.meta);
// 检查是否需要登录
if (to.meta.requiresAuth && !authState.isLoggedIn) {
ElMessage.error(' 请先登录才能访问此页面!');
console.log('❌ 访问被拒绝: 需要登录');
next('/');
return;
}
// 检查是否需要管理员权限
if (to.meta.requiresAdmin && (!authState.isLoggedIn || !authState.isAdmin)) {
if (!authState.isLoggedIn) {
ElMessage.error(' 请先登录!');
console.log('❌ 访问被拒绝: 需要登录');
} else {
ElMessage.error(' 需要管理员权限才能访问此页面!');
console.log('❌ 访问被拒绝: 需要管理员权限');
}
next('/');
return;
}
console.log('✅ 路由守卫通过');
next();
});
// 路由后置守卫 - 记录访问日志
router.afterEach((to, from) => {
console.log(`✅ 路由跳转完成: ${from.path}${to.path}`);
});
// 创建应用
const app = createApp(App);
// 注册图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component);
}
app.use(ElementPlus);
app.use(router);
app.mount('#app');
console.log(' Vue Router 训练应用启动成功!');
</script>
</body>
</html>
posted @ 2025-10-25 21:50  ycfenxi  阅读(0)  评论(0)    收藏  举报