Skip to content

动态路由

https://router.vuejs.org/zh/guide/advanced/dynamic-routing.html

我们一般使用动态路由都是后台会返回一个路由表前端通过调接口拿到后处理 (后端处理路由)

主要使用的方法就是 router.addRoute

添加路由

动态路由主要通过两个函数实现。router.addRoute() 和 router.removeRoute()。它们只注册一个新的路由,也就是说,如果新增加的路由与当前位置相匹配,就需要你用 router.push() 或 router.replace() 来手动导航,才能显示该新路由

javascript
router.addRoute({ path: "/about.md", component: About });

删除路由

有几个不同的方法来删除现有的路由:

通过添加一个名称冲突的路由。如果添加与现有途径名称相同的途径,会先删除路由,再添加路由:

javascript
router.addRoute({ path: "/about.md", name: "about", component: About });
// 这将会删除之前已经添加的路由,因为他们具有相同的名字且名字必须是唯一的
router.addRoute({ path: "/other", name: "about", component: Other });

通过调用 router.addRoute() 返回的回调:

javascript
const removeRoute = router.addRoute(routeRecord);
removeRoute(); // 删除路由如果存在的话

当路由没有名称时,这很有用。

通过使用 router.removeRoute() 按名称删除路由:

javascript
router.addRoute({ path: "/about.md", name: "about", component: About });
// 删除路由
router.removeRoute("about");

需要注意的是,如果你想使用这个功能,但又想避免名字的冲突,可以在路由中使用 Symbol 作为名字。

当路由被删除时,所有的别名和子路由也会被同时删除

查看现有路由 Vue Router 提供了两个功能来查看现有的路由:

javascript
router.hasRoute():检查路由是否存在。
router.getRoutes():获取一个包含所有路由记录的数组。

案例 - 前端代码

App.vue

vue
<script setup>
import { onMounted } from "vue";
import axios from "axios";
import { useRouter } from "vue-router";

const router = useRouter();

// 启动项目之后才加载登录路由
onMounted(async () => {
  const response = await axios.get("http://127.0.0.1:5000/menus");
  const data = response.data;
  data.routes.forEach((v) => {
    router.addRoute({
      path: v.path,
      name: v.name,
      component: () => import(`./views/${v.component}`),
    });
  });
  await router.push("/login");
});
</script>

<template>
  <router-view></router-view>
</template>

<style scoped></style>

Login.vue

vue
<template>
  <div class="login">
    <el-form :model="formInline" class="demo-form-inline">
      <el-form-item label="用户名:">
        <el-input v-model="formInline.username" placeholder="请输入用户名" />
      </el-form-item>

      <el-form-item label="密&nbsp;&nbsp;&nbsp;码:">
        <el-input v-model="formInline.password" placeholder="请输入密码">
        </el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">提交登录</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import axios from "axios";
import { reactive } from "vue";
import { useRouter } from "vue-router";

const router = useRouter();

const formInline = reactive({
  username: "",
  password: "",
});

const onSubmit = async () => {
  const response = await axios.post("http://127.0.0.1:5000/login", formInline);
  const data = response.data;
  console.log(data);

  // 登录成功之后,解析后端返回的路由数据
  if (data?.routes) {
    data.routes.forEach((v) => {
      console.log(v);
      const path = v?.parent
        ? `./${v.parent}/${v.component}`
        : `./${v.component}`;

      router.addRoute("main", {
        path: "/main" + v.path,
        name: v.name,
        component: () => import(path),
      });
    });
    console.log(router.getRoutes());
    await router.push("/main");
  }
};
</script>

<style scoped>
.login {
  width: 30%;
  margin: 100px auto;
}
</style>

Main.vue

vue
<template>
  <h1>Main</h1>
  <div class="nav">
    <router-link to="/main/articles">阅读文章</router-link>
    <router-link to="/main/hot">排行热榜</router-link>
    <router-link to="/main/author">作者排行</router-link>
  </div>
  <div class="subview">
    <router-view></router-view>
  </div>
</template>

<script setup></script>

<style scoped>
.nav a {
  margin: 20px;
}
</style>

router/index.js

js
import { createRouter, createWebHistory } from "vue-router";

const routes = [
  // {
  //     path: '/login',
  //     name: 'login',
  //     component: () => import('../views/Login.vue')
  // },
  // {
  //     path: '/main',
  //     name: 'main',
  //     component: () => import('../views/Main.vue')
  // }
];

const router = createRouter({
  history: createWebHistory(),
  routes: routes,
});

export default router;

案例 - 后端代码

python
from flask import Flask, request
from flask_cors import CORS

app = Flask(__name__)
CORS().init_app(app)


@app.route('/login', methods=['POST'])
def login():
    username = request.json.get('username')
    password = request.json.get('password')
    if username == 'admin' and password == '123456':
        return {
            'routes': [
                {
                    'path': "/articles",
                    'name': "articles",
                    'parent': "subviews",
                    'component': 'Articles.vue'
                },
                {
                    'path': "/hot",
                    'name': "hot",
                    'parent': "subviews",
                    'component': 'Hot.vue'
                },
                {
                    'path': "/author",
                    'name': "author",
                    'parent': "subviews",
                    'component': 'Author.vue'
                }
            ]
        }
    else:
        return {
            'code': 400,
            'message': "账号密码错误"
        }


@app.route('/menus', methods=['GET'])
def menus():
    return {
        'routes': [
            {
                'path': '/login',
                'name': 'login',
                'component': 'Login.vue'
            },
            {
                'path': '/main',
                'name': 'main',
                'component': 'Main.vue'
            }
        ]
    }


@app.route('/', methods=['GET'])
def index():
    return {
        'routes': [
            {
                'path': '/login',
                'name': 'login',
                'component': './views/Login.vue'
            }
        ]
    }


if __name__ == '__main__':
    app.run(debug=True, host='127.0.0.1', port=5000)