vue3中使用antd-vue实现面包屑导航

该文描述了一个Vue应用中如何配置路由实现登录后默认选中第一个动态栏目,并在点击不同模块时动态更新面包屑导航标题。通过使用`router.ts`设置路由规则,以及在`Home.vue`组件中处理菜单的显示,利用`<a-menu>`和`<a-sub-menu>`组件动态生成菜单结构,同时通过`watch`监听路由变化来更新面包屑信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

期望的实现效果,登录后进入主页,默认选中第一个动态栏目,点击下面任意模块,右侧面包屑能够动态改变标题。

router.ts模块

const routes: RouteRecordRaw[] = [
  {
    path: "/",
    redirect: "/login",
  },
  {
    path: "/login",
    name: "login",
    component: () => import("../views/Login.vue"),
    children: [],
  },

  {
    path: "/home",
    name: "home",
    redirect: "/home/dynamic",
    component: () => import("../views/Home.vue"),
    children: [
      {
        path: "dynamic",
        meta: {
          title: ["动态"],
        },
        name: "dynamic",
        component: () => import("../views/routerCmp/dynamic.vue"),
      },
      {
        path: "buseness",
        name: "buseness",
        meta: {
          title: ["业务模块", "业务部功能使用情况"],
        },
        component: () => import("../views/routerCmp/buseness.vue"),
      },
      {
        path: "menuManage",
        name: "menuManage",
        meta: {
          title: ["系统模块", "菜单管理"],
        },
        component: () => import("../views/routerCmp/setting.vue"),
      },
    ],
  },
];

home.vue 

<template>
<a-layout style="min-height: 100vh">
      <a-layout-sider>
        <div class="logoBox"><div class="logo"></div></div>
        <a-menu
          theme="dark"
          mode="inline"
          v-model:selectedKeys="SelectedKey"
          :openKeys="openKeys"
          @click="handleClick"
        >
          <template v-for="item in cardList">
            <a-menu-item v-if="!item.children" :key="item.id">
              <router-link :to="item.path"
                ><div class="menustyle">
                  <span :class="IconType[item.id]"></span>
                  <span>{{ item.name }}</span>
                </div></router-link
              >
            </a-menu-item>
            <a-sub-menu v-else :key="item.path">
              <template #title>
                <div class="menustyle">
                  <span :class="IconType[item.id]"></span>
                  <span>{{ item.name }}</span>
                </div>
              </template>
              <a-menu-item :key="children.id" v-for="children in item.children"
                ><router-link :to="children.path">{{
                  children.name
                }}</router-link></a-menu-item
              >
            </a-sub-menu>
          </template>
        </a-menu>
      </a-layout-sider>
      <a-layout>
        <a-layout-header style="background: #fff" class="navTitle">
          <div class="titleBox">
            <a-breadcrumb>
              <a-breadcrumb-item v-for="item in breadCumber">{{
                item
              }}</a-breadcrumb-item>
            </a-breadcrumb>
            <div class="UserBox">
              <div class="userIcon"></div>
              <div>用户名</div>
              <div class="UserBoxhover">
                <div class="logout" @click="logoutFn">退出登录</div>
              </div>
            </div>
          </div>
        </a-layout-header>
        <a-layout-content class="layoutstyle">
          <div class="bodyContent"><router-view></router-view></div>
        </a-layout-content>
      </a-layout>
    </a-layout>
</template>
<script lang="ts" setup>
import { ElMessage } from "element-plus";
import { onMounted, ref, watch } from "vue";
import { getMenu } from "../api/home";
import { useRoute, useRouter } from "vue-router";
interface MenuType {
  name: string;
  parentId?: number;
  path: string;
  id: string;
}
const router = useRouter();
const menuList = ref<MenuType[]>();
const routes = useRoute();
const openKeys = ref<string[]>(
  sessionStorage.getItem("tabActive")
    ? JSON.parse(sessionStorage.getItem("tabActive") || "")
    : []
);
const breadCumber = ref(routes.meta.title);
const SelectedKey = ref<string[]>(
  sessionStorage.getItem("tabActive")
    ? JSON.parse(sessionStorage.getItem("tabActive") || "")
    : ["1"]
);
const IconType: { [key: string]: string } = {
  1: "dynamic",
  2: "buseness",
};

const handleClick = (e: any) => {
//防止刷新后状态重置
  SelectedKey.value = e.keyPath;
  openKeys.value = e.keyPath;
  sessionStorage.setItem("tabActive", JSON.stringify(e.keyPath));
};


//监听路由中的meta值改变
watch(
  () => routes.meta,
  () => {
    breadCumber.value = routes.meta.title;
  }
);
//模拟数据
const cardList = ref([
  { id: "1", name: "动态", path: "/home/dynamic" },
  {
    id: "2",
    name: "业务模块",
    path: "buseness",
    children: [{ id: "4", name: "业务部功能使用情况", path: "/home/buseness" }],
  },
  {
    id: "3",
    name: "系统模块",
    path: "setting",
    children: [
      {
        id: "5",
        name: "菜单管理",
        path: "/home/menuManage",
      },
    ],
  },
]);
</script>

 记录一下,当我去v-for左侧的菜单数组时,我需要在中间去判断是显示<a-sub-menu>还是<a-menu-item>,有子元素children就显示<a-sub-menu>,没有子元素就显示<a-menu-item>。

一开始,我给这两个元素的key值都是item.id,但这个时候虽然页面不报错,但代码会标红并且提示我只能有唯一key值,我只能在v-if的模块给item.id,在v-else的模块给item.path。

antd-vue中控制<a-sub-menu>是否展开是openKeys

默认选中是SelectedKey

路由跳转的地方我使用了router-link,也可以写单独的函数去router.push({name:'xxx',query:{ }})

其中query可以传递相关参数到目的页面

因为我的面包屑不要求实现点击跳转,仅仅作为文字展示,所有没有写相关跳转逻辑

Vue3 中,结合 Ant Design Vue (ant-design-vue) 实现分页表格通常需要以下几个步骤: 1. 安装依赖:首先确保已经安装了 Vueantd-design-vue,可以使用 `npm` 或 `yarn` 来安装: ```bash npm install vue@^3.0 antd @ant-design/icons # 或者 yarn add vue@next antd @ant-design/icons ``` 2. 导入组件:在你的 `.vue` 文件中导入需要的组件,如 `Table`, `Pagination` 和 `Icon`: ```javascript import { Table, Pagination } from &#39;ant-design-vue&#39;; import PlusOutlined from &#39;@ant-design/icons/PlusOutlined&#39;; ``` 3. 创建数据源:你可以创建一个虚拟的数据数组,模拟分页效果: ```javascript const dataSource = Array.from({ length: 50 }, (_, index) => ({ key: `${index}`, name: `Name ${index + 1}`, age: `Age ${index + 1}`, address: `Address ${index + 1}`, })); ``` 4. 使用 `v-model` 绑定分页插件,并监听它的变化事件来动态加载数据: ```html <template> <div> <a-icon :type="currentMode === &#39;prev&#39; ? &#39;chevron-left&#39; : &#39;chevron-right&#39;" slot="prev" @click="changePage(-1)" /> <Pagination :total="total" :current="currentPage" @on-change="changePage" /> <Table :data="filteredData" :columns="columns" :pagination="pagination" /> <a-icon type="plus" @click="addRow" /> </div> </template> // ... data() { return { currentPage: 1, pageSize: 10, dataSource, total: dataSource.length, columns: [ // ...你的列配置 ], pagination: { pageSizes: [10, 20, 30], // 可选分页大小选项 }, }; }, methods: { changePage(page) { this.currentPage = page; }, filteredData() { return this.dataSource.slice((this.currentPage - 1) * this.pageSize, this.currentPage * this.pageSize); }, addRow() { this.dataSource.push({ // ...添加新的行数据 }); this.total++; } } ``` 5. 根据需求定制表头、排序、搜索等功能,如果需要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值