实现一个简单的后台架子(侧边栏菜单渲染,折叠,黑白主题,组件主题色,全屏,路由快捷栏)

发布于:2024-12-18 ⋅ 阅读:(138) ⋅ 点赞:(0)

目录

侧边栏菜单渲染

侧边栏折叠

黑白主题

全屏切换

切换组件主题色

tab快捷栏

代码


侧边栏菜单渲染

结合ElementPlus组件库进行实现

新建的Vue3项目,引入了格式化样式normalize.css和ElementPlus,并进行了全局引入

并进行了全局引入

设置高度为100%

粘贴ElementPlus的布局容器代码,到HomeView.vue文件中,并进行简单修改

<template>
  <div class="contioner">
    <el-container class="layout-container-demo" style="height: 100%">
      <!-- 侧边栏 START -->
      <el-aside width="200px">
        <el-scrollbar>
          <el-menu router>
            <!-- 一级菜单 -->
            <el-menu-item index="1-4-1">一级菜单</el-menu-item>
            <!-- 子级菜单 -->
            <el-sub-menu index="1">
              <template #title>
                <el-icon><message /></el-icon>子级菜单
              </template>
              <el-menu-item index="1-4-1">孙子菜单1</el-menu-item>
              <el-sub-menu index="1-4">
                <template #title>孙子菜单2</template>
                <el-menu-item index="1-4-1">重孙菜单</el-menu-item>
              </el-sub-menu>
            </el-sub-menu>
          </el-menu>
        </el-scrollbar>
      </el-aside>
      <!-- 侧边栏 END -->

      <!-- 内容区 START -->
      <el-container>
        <el-header style="text-align: right; font-size: 12px">
          <div class="toolbar">
            <el-dropdown>
              <el-icon style="margin-right: 8px; margin-top: 1px">
                <setting />
              </el-icon>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item>View</el-dropdown-item>
                  <el-dropdown-item>Add</el-dropdown-item>
                  <el-dropdown-item>Delete</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <span>Tom</span>
          </div>
        </el-header>

        <el-main>
          <el-scrollbar>
            <!-- 路由出口,可以展示子级菜单内容 -->
            <router-view></router-view>
          </el-scrollbar>
        </el-main>
      </el-container>
      <!-- 内容区 END -->
    </el-container>
  </div>
</template>

<script setup lang="ts">
import { Message, Setting } from '@element-plus/icons-vue'
</script>

<style scoped>
.contioner {
  width: 100%;
  height: 100%;
}

.layout-container-demo .el-header {
  position: relative;
  background-color: var(--el-color-primary-light-7);
  color: var(--el-text-color-primary);
}
.layout-container-demo .el-aside {
  color: var(--el-text-color-primary);
  background: var(--el-color-primary-light-8);
}
.layout-container-demo .el-menu {
  border-right: none;
}
.layout-container-demo .el-main {
  padding: 0;
}
.layout-container-demo .toolbar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  right: 20px;
}
</style>

效果图如下,一个简单的后台架子就出来了

然后开始路由新增

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView,
      children: [
        {
          path: '/test1',
          name: 'test1',
          component: () => import('@/views/ParentPage.vue'),
        },
        {
          path: '/test2',
          name: 'test2',
          children: [
            {
              path: '/test3',
              name: 'test3',
              component: () => import('@/views/SonPage.vue'),
            },
            {
              path: '/test4',
              name: 'test4',
              children: [
                {
                  path: '/test5',
                  name: 'test5',
                  component: () => import('@/views/SonPage.vue'),
                },
              ],
            },
          ],
        },
      ],
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/AboutView.vue'),
    },
  ],
})

export default router

在views下新增ParentPage.vue和SonPage.vue文件

路由定义好了,就可以在HomeView.vue文件中引入路由数据了

<script setup lang="ts">
import { Message, Setting } from '@element-plus/icons-vue'
import { computed } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()

// 路由数据
const routes = computed(() => {
  return router.getRoutes().filter(p => p.path === '/')[0].children
})
</script>

多级菜单渲染,需要用到递归组件,所以我们把侧边栏菜单展示进行封装,views下新建MenuTree.vue

<template>
  <div>
    <template v-for="i in routes" :key="i.path">
      <!-- 一级菜单 -->
      <el-menu-item :index="i.path" v-if="!i.children">
        {{ i.path }}
      </el-menu-item>
      <!-- 子级菜单 -->
      <el-sub-menu :index="i.path" v-else>
        <template #title>
          <el-icon><message /></el-icon>{{ i.path }}
        </template>
        <!-- 使用递归组件,传递嵌套路由数据 -->
        <MenuTree :routes="i.children"></MenuTree>
      </el-sub-menu>
    </template>
  </div>
</template>

<script setup lang="ts">
import { Message } from '@element-plus/icons-vue'
import type { RouteRecordRaw } from 'vue-router'

defineProps({
  routes: {
    type: Array<RouteRecordRaw>,
    default: () => [],
  },
})
</script>

最后在HomeView.vue中引入此组件

      <!-- 侧边栏 START -->
      <el-aside width="200px">
        <el-scrollbar>
          <el-menu router>
            <MenuTree :routes="routes"></MenuTree>
          </el-menu>
        </el-scrollbar>
      </el-aside>
      <!-- 侧边栏 END -->

此时就完成了侧边栏菜单的渲染

侧边栏折叠

然后再加一个侧边栏折叠的功能

添加一个按钮到头部,修改HomeView.vue

结构处修改:
        <el-header>
          <el-button type="primary" size="small">折叠/展开</el-button>
          <div class="toolbar">
            <el-dropdown>
              <el-icon style="margin-right: 8px; margin-top: 1px">
                <setting />
              </el-icon>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item>View</el-dropdown-item>
                  <el-dropdown-item>Add</el-dropdown-item>
                  <el-dropdown-item>Delete</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <span>Tom</span>
          </div>
        </el-header>



样式处修改:
.layout-container-demo .el-header {
  position: relative;
  background-color: var(--el-color-primary-light-7);
  color: var(--el-text-color-primary);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

页面效果

然后修改侧边栏代码  修改HomeView.vue

结构处修改
      <!-- 侧边栏 START -->
      <!-- width="collapse" 可以让侧边栏宽度正好合适!!! -->
      <el-aside width="collapse">
        <el-scrollbar>
          <el-menu router class="el-menu-vertical-demo" :collapse="isCollapse">
            <MenuTree :routes="routes"></MenuTree>
          </el-menu>
        </el-scrollbar>
      </el-aside>
      <!-- 侧边栏 END -->



逻辑处新增:
// 折叠状态
const isCollapse = ref(false)
// 折叠/展开
const collapseChange = () => {
  isCollapse.value = !isCollapse.value
}


样式处新增:
/* 侧边栏宽度 */
.el-menu-vertical-demo:not(.el-menu--collapse) {
  width: 200px;
}

MenuTree.vue修改

<template>
  <template v-for="i in routes" :key="i.path">
    <!-- 一级菜单 -->
    <el-menu-item :index="i.path" v-if="!i.children">
      {{ i.path }}
    </el-menu-item>
    <!-- 子级菜单 -->
    <el-sub-menu :index="i.path" v-else>
      <template #title>
        <el-icon><message /></el-icon>
        <!-- 标题一定要用标签包裹,不然折叠的时候会显示一部分字!!! -->
        <span>{{ i.path }}</span>
      </template>
      <!-- 使用递归组件,传递嵌套路由数据 -->
      <MenuTree :routes="i.children"></MenuTree>
    </el-sub-menu>
  </template>
</template>

看下效果:

  • 折叠

  • 展开

黑白主题

然后再加个黑白主题吧(ElementPlus本身就有此功能)暗黑模式 | Element Plus

首先在main.ts中引入暗色主题

import 'element-plus/theme-chalk/dark/css-vars.css'

然后在HomeView.vue中新增切换按钮并添加逻辑处理

结构处修改:       
        <el-header>
          <el-button type="primary" size="small" @click="collapseChange"
            >折叠/展开</el-button
          >
          <div class="toolbar">
            <el-switch
              inline-prompt
              v-model="theme"
              active-text="暗黑"
              inactive-text="白亮"
              @change="toggle"
            />
            <el-dropdown>
              <el-icon style="margin-right: 8px; margin-top: 1px">
                <setting />
              </el-icon>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item>View</el-dropdown-item>
                  <el-dropdown-item>Add</el-dropdown-item>
                  <el-dropdown-item>Delete</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <span>Tom</span>
          </div>
        </el-header>


逻辑处修改:
// 引入切换主题的hook
import { useDark, useToggle } from '@vueuse/core'

// 主题状态
const theme = ref(localStorage.getItem('theme') === 'dark' ? true : false)

// 切换主题
const isDark = useDark({
  // 存储到localStorage中的Key 根据自己的需求更改
  storageKey: 'theme',
  // 暗黑class名字
  valueDark: 'dark',
  // 高亮class名字
  valueLight: 'light',
})
const toggle = useToggle(isDark)

但是这个只实现了在组件库的主题切换,我们自己写的代码也要实现主题切换,可以在assets文件夹下新建theme文件夹,再新建theme.scss文件

// 主题
$themes: (
  // 白亮: 设置一些字体颜色,背景色什么的
  light:
    (
      background: #fff,
      color: #000,
      textColor: #000,
    ),
  // 暗黑
  dark:
    (
      background: #121212,
      color: #fff,
      textColor: #fff,
    )
);

// 当前主题
$curTheme: light;

// 混合
// @mixin useTheme() {
//     html[data-theme='light'] & {
//         background-color: #fff;
//         color: #000;
//     }
//     html[data-theme='dark'] & {
//         background-color: #121212;
//         color: #fff;
//     }
// }

// 混合优化(遍历上面的主题)
@mixin useTheme() {
  @each $key, $value in $themes {
    $curTheme: $key !global; // 当前的主题
    html[data-theme='#{$key}'] & {
      // & 表示传入什么选择器就是什么选择器
      @content; // 类似于插槽,样式可以进行传入
    }
  }
}

// 生成对应主题的变量
@function getVar($key) {
  $themeMap: map-get($themes, $curTheme);
  @return map-get($themeMap, $key);
}

全局引入此scss文件

import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
  // 配置全局scss文件
  css: {
    preprocessorOptions: {
      // 引入全局的scss文件
      scss: {
        additionalData: `@import "./src/assets/theme/theme.scss";`,
      },
    },
  },
})

找个测试页面测试即可

<template>
  <div>
    <h2>父级页面</h2>
    <div class="box"></div>
    <div class="mb-4">
      <el-button>Default</el-button>
      <el-button type="primary">Primary</el-button>
      <el-button type="success">Success</el-button>
      <el-button type="info">Info</el-button>
      <el-button type="warning">Warning</el-button>
      <el-button type="danger">Danger</el-button>
    </div>
  </div>
</template>

<script setup lang="ts"></script>

<style scoped>
.box {
  width: 100%;
  height: 200px;
  /* 使用主题变量 */
  background-color: getVar('background');
}
</style>

全屏切换

再做一个切换全屏的效果

安装一个screenfull插件

npm i screenfull

然后修改HomeView.vue的代码

结构处修改:        
<el-header>
          <el-button type="primary" size="small" @click="collapseChange"
            >折叠/展开</el-button
          >
          <div class="toolbar">
            <el-switch
              inline-prompt
              v-model="theme"
              active-text="暗黑"
              inactive-text="白亮"
              @change="toggle"
            />

            <el-button type="primary" size="small" @click="screenfullChange"
              >全屏/非全屏</el-button
            >

            <el-dropdown>
              <el-icon style="margin-right: 8px; margin-top: 1px">
                <setting />
              </el-icon>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item>View</el-dropdown-item>
                  <el-dropdown-item>Add</el-dropdown-item>
                  <el-dropdown-item>Delete</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <span>Tom</span>
          </div>
        </el-header>


逻辑处修改:
import screenfull from 'screenfull'
import { ElMessage } from 'element-plus'

// 全屏/非全屏
const screenfullChange = () => {
  if (!screenfull.isEnabled) {
    return ElMessage({ message: '你的浏览器不支持全屏', type: 'warning' })
  }
  screenfull.toggle()
}

切换组件主题色

如果不喜欢ElementPlus的组件配色,也可以自己进行修改:  主题 | Element Plus

新建styles文件夹,然后再新建element文件夹,然后再新建index.scss文件,粘贴以下代码

// styles/element/index.scss
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  ),
);

// 如果只是按需导入,则可以忽略以下内容。
// 如果你想导入所有样式:
@use "element-plus/theme-chalk/src/index.scss" as *;

然后再修改main.ts,更换引入的scss文件

import ElementPlus from 'element-plus'

// import 'element-plus/dist/index.css'  // 更换完下面的scss文件,因为下面的scss文件中已经引入了所有样式
import './styles/element/index.scss'

此时就已经修改成功了,组件主题色都变成了我们设置的颜色

但是如果想通过按钮修改主题色呢?比如下面的效果

我们应该这么做

新增一个处理设置组件主题颜色的函数:在utils文件夹下新增theme.ts

// import { useCssVar } from '@vueuse/core'

type RGB = {
  r: number
  g: number
  b: number
}

const rgbWhite = {
  r: 255,
  g: 255,
  b: 255,
}
const rgbBlack = {
  r: 0,
  g: 0,
  b: 0,
}

function componentToHex(c: number): string {
  const hex = Math.round(c).toString(16)
  return hex.length === 1 ? '0' + hex : hex
}

function rgbToHex(rgb: RGB): string {
  return `#${componentToHex(rgb.r)}${componentToHex(rgb.g)}${componentToHex(rgb.b)}`
}

function mix(color: RGB, mixColor: RGB, weight: number): RGB {
  return {
    r: color.r * (1 - weight) + mixColor.r * weight,
    g: color.g * (1 - weight) + mixColor.g * weight,
    b: color.b * (1 - weight) + mixColor.b * weight,
  }
}

/**
 * hex 转换为 rgb
 * @param hex 例如 #FF0000
 */
function hexToRGB(hex: string): RGB {
  if (!/^[0-9A-Fa-f]{3}$|[0-9A-Fa-f]{6}$/.test(hex)) {
    throw new Error('请传入合法的16进制颜色值,eg: #FF0000')
  }
  // 移除可能存在的 # 符号
  hex = hex.replace('#', '')
  // 确保十六进制代码是有效的

  // 返回 RGB 对象
  return {
    r: parseInt(hex.slice(0, 2), 16),
    g: parseInt(hex.slice(2, 4), 16),
    b: parseInt(hex.slice(4, 6), 16),
  }
}

/**
 * 修改 element-plus的颜色主题
 */
function updateElementPlusTheme(type: string, baseColor: string): void {
  // 针对 element-plus 进行修改
  const colorArray: Record<string, string>[] = [
    { className: `--el-color-${type}`, color: rgbToHex(mix(hexToRGB(baseColor), rgbBlack, 0)) },
    {
      className: `--el-color-${type}-dark-2`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbBlack, 0.2)),
    },
    {
      className: `--el-color-${type}-light-3`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.3)),
    },
    {
      className: `--el-color-${type}-light-5`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.5)),
    },
    {
      className: `--el-color-${type}-light-7`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.7)),
    },
    {
      className: `--el-color-${type}-light-8`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.78)),
    },
    {
      className: `--el-color-${type}-light-9`,
      color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.85)),
    },
  ]

  // document.documentElement 是全局变量时
  // const el = document.documentElement

  colorArray.forEach((item) => {
    // 下面两种方式都可以
    // 方法1: 需要把顶部的导入解开
    // const color = useCssVar(item.className, document.documentElement)
    // color.value = item.color
    // 方法2:
    document.documentElement.style.setProperty(item.className, item.color)
    // 方法3: 把上面的el解开
    // 获取 css 变量
    // getComputedStyle(el).getPropertyValue(item.className)
    // 设置 css 变量
    // el.style.setProperty(item.className, item.color)
  })
}

export { type RGB, hexToRGB, rgbToHex, updateElementPlusTheme }

修改HomeView.vue:

结构处修改:
            <!-- 颜色选择器 -->
            <el-color-picker
              v-model="color"
              :predefine="predefineColors"
              @change="setThemeColor"
              color-format="hex"
              :show-alpha="false"
            />

逻辑处修改:
import { updateElementPlusTheme } from '@/utils/theme'

// 颜色
const color = ref(localStorage.getItem('theme-color') || '#409EFF')
// 组件预定义颜色
const predefineColors = ref([
  '#ff4500',
  '#ff8c00',
  '#ffd700',
  '#90ee90',
  '#00ced1',
  '#1e90ff',
  '#c71585',
  'rgba(255, 69, 0, 0.68)',
  'rgb(255, 120, 0)',
  'hsv(51, 100, 98)',
  'hsva(120, 40, 94, 0.5)',
  'hsl(181, 100%, 37%)',
  'hsla(209, 100%, 56%, 0.73)',
  '#c7158577',
])

/**
 * 设置主题颜色
 * @param type 类型
 * @param color 颜色
 */
const setThemeColor = (color: string, type = 'primary') => {
  // 存入本地主题颜色的值
  if (localStorage.getItem('theme-color') !== color) {
    localStorage.setItem('theme-color', color)
  }

  // 更新 Element Plus 主题
  updateElementPlusTheme(type, color)
}

看下效果

但是刷新后还是会丢失,所以我们在App.vue中重新设置下组件的主题颜,刷新后也不会丢失

import { onMounted } from 'vue'
import { updateElementPlusTheme } from './utils/theme'

onMounted(() => {
  updateElementPlusTheme(
    'primary',
    localStorage.getItem('theme-color') || '#409EFF',
  )
})

tab快捷栏

设置快捷栏需要用到pinia持久化,所以我们要先下载一个持久化插件

npm i pinia-plugin-persistedstate

然后修改counter.ts

import { ref } from 'vue'
import { defineStore, createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import router from '@/router'
import { ElMessage } from 'element-plus'

// 创建仓库
const pinia = createPinia()

// 使用插件进行持久化存储
pinia.use(piniaPluginPersistedstate)

interface IHistoryList {
  path: string
  name: string
}

export const useCounterStore = defineStore(
  'counter',
  () => {
    const historyList = ref<IHistoryList[]>([])

    // 设置菜单历史记录列表的方法
    const setHistoryList = ({ path, name }: IHistoryList) => {
      // 没有就添加
      if (historyList.value.findIndex(i => i.path === path) === -1) {
        historyList.value.push({ path, name })
      }
    }
    // 清除某个菜单历史记录列表的方法
    const clearHistory = (path: string) => {
      // 如果只剩下一个路由,则弹窗提示,不操作
      if (historyList.value.length === 1) {
        return ElMessage.warning('只剩下一个路由了,无法删除')
      }
      // 跳转到后一个路由
      const index = historyList.value.findIndex(i => i.path === path)
      // 如果是最后一个路由则跳转到前一个路由
      if (index === historyList.value.length - 1) {
        router.push(historyList.value[index - 1].path)
      } else {
        router.push(historyList.value[index + 1].path)
      }
      // 删除该路由
      historyList.value = historyList.value.filter(i => i.path !== path)
    }

    return { historyList, setHistoryList, clearHistory }
  },
  {
    // 设置持久化
    persist: {
      key: 'settingInfo',
      storage: sessionStorage,
    },
  },
)

然后还需要修改一下路由配置,也就是router文件夹下的index.ts。设置了首页重定向,然后新增了一个全局路由前置守卫(监听路由跳转,好往路由历史数组里添加路由信息)

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import { useCounterStore } from '@/stores/counter'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: HomeView,
      // 首页进来重定向到test1
      redirect: '/test1',
      children: [
        {
          path: '/test1',
          name: 'test1',
          component: () => import('@/views/ParentPage.vue'),
        },
        {
          path: '/test2',
          name: 'test2',
          children: [
            {
              path: '/test3',
              name: 'test3',
              component: () => import('@/views/SonPage.vue'),
            },
            {
              path: '/test4',
              name: 'test4',
              children: [
                {
                  path: '/test5',
                  name: 'test5',
                  component: () => import('@/views/SonPage.vue'),
                },
              ],
            },
          ],
        },
      ],
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/AboutView.vue'),
    },
  ],
})

// 全局前置路由守卫
router.beforeEach(to => {
  const path = to.path
  const name = to.name as string

  useCounterStore().setHistoryList({ path, name })

  return true
})

export default router

最后修改HomeView.vue文件
 

结构处修改:
        <el-header>
          <div class="header">
            <el-button type="primary" size="small" @click="collapseChange">折叠/展开</el-button>
            <div class="toolbar">
              <el-switch inline-prompt v-model="theme" active-text="暗黑" inactive-text="白亮" @change="toggle" />

              <el-button type="primary" size="small" @click="screenfullChange">全屏/非全屏</el-button>

              <!-- 颜色选择器 -->
              <el-color-picker v-model="color" :predefine="predefineColors" @change="setThemeColor" color-format="hex"
                :show-alpha="false" />

              <el-dropdown>
                <el-icon style="margin-right: 8px; margin-top: 1px">
                  <setting />
                </el-icon>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item>View</el-dropdown-item>
                    <el-dropdown-item>Add</el-dropdown-item>
                    <el-dropdown-item>Delete</el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
              <span>Tom</span>
            </div>
          </div>
          <el-tag v-for="tag in store.historyList" :key="tag.name" closable @click="toPath(tag.path)"
            @close="delHistory(tag.path)" class="ml-2">
            {{ tag.name }}
          </el-tag>
        </el-header>


逻辑处修改:
import { useCounterStore } from '@/stores/counter'

const store = useCounterStore()

// 删除历史记录
const delHistory = (path: string) => {
  store.clearHistory(path)
}
// 跳转路由
const toPath = (path: string) => {
  router.push(path)
}

样式处修改:
.layout-container-demo .el-header {
  position: relative;
  background-color: var(--el-color-primary-light-7);
  color: var(--el-text-color-primary);
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.ml-2 {
  margin-left: 8px;
}

效果:

至于想实现下面的效果

可以使用ElementPlus的Dropdown组件,做出修改即可,本质就是操作pinia中存储的路由历史数组

代码

通过网盘分享的文件:test.zip
链接: https://pan.baidu.com/s/1mmGT_xjW52s9dKUVJNZE2Q?pwd=atm8 提取码: atm8

写的很糙,关注实现即可。有空闲时间了,还会加上中英文切换


网站公告

今日签到

点亮在社区的每一天
去签到