前中台项目

svg图标原理;面包屑组件代码;tabs代码

1.SVG图标完整流程(极简流程图)

ini 复制代码
你把 hamburger.svg 放到 src/assets/icons
        ↓
vite‑plugin‑svg‑icons(启动时扫描文件夹)
        ↓
读取svg内容 → 包装成 <symbol id="icon‑hamburger">
        ↓
自动注入隐藏svg到页面DOM(display:none,肉眼看不见)
        ↓
main.js import 'virtual:svg-icons-register' 【必须!触发插件生效】
        ↓
你的页面使用组件 <m-svg-icon name="hamburger"/>
        ↓
组件计算 symbolId → #icon‑hamburger
        ↓
<use :xlink:href="#icon‑hamburger"> 找到页面里的symbol
        ↓
渲染图形 → 出现汉堡三条杠 ✅

必记3个坑

  1. 忘了 import 'virtual:svg-icons-register'全部图标空白
  2. 修改svg文件,不重启vite → 不更新symbol,图标不变
  3. svg源码写死 fill="#000" → 组件传color改不了颜色

对应代码位置速查

  1. vite.config.js → createSvgIconsPlugin,配置iconDirs图标目录
  2. main.js → import 'virtual:svg-icons-register'
  3. src/libs/svg‑icon/index.vue → m‑svg‑icon 组件
  4. 使用:<m-svg-icon name="hamburger"/>

回忆之前: name="hamburger" 不要写 icon‑,组件内部自动拼接成 #icon‑hamburger

2.面包屑核心来源:$route.matched

$route.matched 是路由匹配数组,保存当前路由每一层级

举例路由配置

js 复制代码
const routes = [
  {
    path: '/',
    name: 'home',
    meta: { title: '首页' },
    children: [
      {
        path: '/system',
        meta: { title: '系统管理' },
        children: [
          {
            path: '/system/user',
            meta: { title: '用户管理' }
          }
        ]
      }
    ]
  }
]

访问 /system/user$route.matched 得到数组:

js 复制代码
[
  { path:'/', meta:{title:'首页'} },
  { path:'/system', meta:{title:'系统管理'} },
  { path:'/system/user', meta:{title:'用户管理'} }
]

面包屑就遍历这个数组,取出每个的 meta.title,拼接:首页 / 系统管理 / 用户管理

Vue3 script‑setup 简易伪代码

vue 复制代码
<template>
  <div class="breadcrumb">
    <span v-for="item in breadList" :key="item.path">
      {{ item.meta.title }}
      <span v-if="!isLast(item)"> / </span>
    </span>
  </div>
</template>

<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()

// 直接拿到层级数组
const breadList = route.matched
</script>

关键点:

  1. 面包屑不会生成不在路由层级里的页面 ,完全靠路由配置的 meta.title
  2. 最后一项(当前页面)一般不给跳转链接,前面层级加 to 跳转
  3. 若依就是基于这套逻辑封装的 el‑breadcrumb

三者再快速复盘(面试脑图)

  1. 汉堡按钮:控制侧边栏展开/收起(按钮)
  2. 侧边导航栏:全部功能入口,跳转任意页面,读取路由全部菜单
  3. 面包屑route.matched,只看当前这条路径的层级,回退上层
  4. Tabs标签页:保存已经打开过的页面记录,可以来回切换、关闭

容易混淆点

  • 侧边导航:全部菜单(完整树)
  • 面包屑:当前路径的一条链(只一条)

面试简答:面包屑怎么实现? 答:通过 vue‑router 的 route.matched 获取路由匹配记录,遍历数组取出路由元信息 meta.title 渲染,除最后一项外绑定路由跳转,实现路径导航。

3.Tabs标签页(若依顶部可关闭页签)

效果:【首页】【用户管理】【角色管理】 ×

核心:自己维护一个数组,不是路由自带的route.matched 给面包屑用;Tabs是手动存你访问过的页面。

核心逻辑

  1. 访问路由的时候,把页面信息push进数组(不要重复添加)
  2. 循环数组渲染标签
  3. 点击标签:跳转到对应路由
  4. 点关闭×:把这条从数组删掉
  5. 不能关闭首页

伪代码 Vue3 setup

vue 复制代码
<template>
  <div class="tabs">
    <span
      v-for="tab in tabList"
      :key="tab.path"
      @click="$router.push(tab.path)"
    >
      {{ tab.title }}
      <!-- 首页不显示关闭按钮 -->
      <span v-if="tab.path !== '/' " @click="closeTab(tab)">×</span>
    </span>
  </div>
</template>

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

const route = useRoute()
const router = useRouter()

// 存已经打开的页签,这个就是tabs数据源
const tabList = ref([
  { path: '/', title: '首页' } // 默认首页一定存在
])

// 监听路由变化,每次跳转路由触发
watch(
  () => route.path,
  () => {
    // 判断这个页签是否已经存在,不存在才push
    const has = tabList.value.some(item => item.path === route.path)
    if (!has) {
      tabList.value.push({
        path: route.path,
        title: route.meta.title
      })
    }
  },
  { immediate: true }
)

// 关闭标签
const closeTab = (tab) => {
  // 删除当前tab
  tabList.value = tabList.value.filter(item => item.path !== tab.path)
}
</script>

三个组件数据来源对比(重点,面试常考)

组件 数据来自哪里
侧边菜单导航 完整路由树 routes,过滤掉不需要显示的路由
面包屑 route.matched,当前路由向上的整条链路
Tabs标签页 自己维护数组,监听路由跳转手动收集访问记录

关键点:

  • 面包屑的数据路由自带;
  • Tabs路由没有给你存,需要自己写状态保存访问记录 ,刷新页面会全部消失(若依用sessionStorage持久化,刷新还在)

完整后台布局三件套总结

  1. 汉堡hamburger按钮 点击切换侧边栏展开/收起状态(存pinia)

  2. 侧边导航菜单 遍历完整路由配置树,渲染全部菜单,点击跳转页面

  3. 面包屑 breadcrumb route.matched,拿到当前路径链条,渲染路径导航

  4. Tabs多标签页 watch监听路由变化,手动维护数组,存放访问过的页面,支持切换关闭


面试简短口述版本

后台管理系统常见三个导航组件: 1.侧边菜单:遍历全部路由树生成,作为系统功能入口; 2.面包屑:使用route.matched获取当前路由匹配层级,取出meta标题渲染路径,实现上层跳转; 3.Tabs标签页:自己维护数组,监听路由变化收集访问过的页面,支持切换关闭,一般存sessionStorage做刷新持久化。

相关推荐
mldong7 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排7 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60618 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角9 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!9 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰9 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi11 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen11 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马12 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒12 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端