赞
踩
提示:这里可以添加技术概要
例如:
openAI 的 GPT 大模型的发展历程。
在之前做的后台项目中,菜单、标签页和面包屑之间的联动,自己都是通过在路由前置守卫中,定义bus总线程通过.emit 和 .on 发送拿取需要的数据,然后再做一些自己想要的处理,实现自己想要的结果,后面在修改项目的时候就想要一中比较方便的办法,抛弃了通过bus总线程实现的方法。选择通过状态管理stroe来存储当前的路由信息控制三者的联动效果。
1.创建你的组件文件,nav:菜单 、header:面包屑 、tabs:标签页,然后先把自己的基础页面信息。
2.将这些组件引入到view->index文件中
页面整体效果
2.创建store文件: index.ts 、user.ts 文件名字自己随便取,后面需要引入的时候不要把名称写错了
store //我习惯了命名 store ,实际可以取名 pinia 因为用到的组件库就是这个
* index
* user
index.ts
- import {createPinia} from 'pinia'
- let pinia= createPinia()
- export default pinia
user.ts
- import {defineStore} from 'pinia'
- const useCounterStore = defineStore('appStore',{
- state :()=> ({
- menuiIsCollapse : false , //menu导航栏是否为展开
- NavList: [], //menu导航栏的数据
- TabsList:[], //标签页的显示数据
- NowRouterPath :'' //当前路由
- }),
- actions : {
- //菜单栏的缩放
- updataMenuWidth(status:boolean){
- this.menuiIsCollapse = status
- this.menuiIsCollapse ? document.documentElement.style.setProperty('--el-aside-width', '64px') : document.documentElement.style.setProperty('--el-aside-width', '220px')
- },
- //第一次进入网站获取nav导航栏信息
- oneSetMenuList (obj:any | []){
- this.NavList = obj
- },
- //获取当前的路由信息
- getNowRouterPath(path:object){
- this.NowRouterPath = path.fullPath
- this.screenTabsList(path)
- },
- //筛选tabs的数据显示 不存在就添加到 TabsList 中
- screenTabsList(to_data:object){
- if(this.TabsList.length == 0){
- this.TabsList.push(to_data)
- }else{
- if(!this.TabsList.some(item => item.fullPath == to_data.fullPath)){
- this.TabsList.push(to_data)
- }
- }
- }
- },
- })
-
- export default useCounterStore
3.创建router.ts文件,在src目录下新建router文件夹 - > 新建index.ts文件
- import { createRouter ,createWebHashHistory , createWebHistory } from "vue-router";
- import pinia from '@/store'
- import useUserStore from "@/store/user";
- import { inject } from "vue";
-
- //必须 否则下面使用 _store 会报错
- useUserStore(pinia)
-
- const routes = [你自己的菜单数据]
-
- const router = createRouter({
- history : createWebHashHistory(),
- routes
- })
-
- //前置路由守卫
- router.beforeEach((to, from, next) => {
- //调用 store 在mian.ts中定义
- const _store = inject('store')
- //将当前路由信息传递给store->user.ts中的方法
- _store.getNowRouterPath(to)
-
- const isAuthenticated = checkIfUserIsAuthenticated();
- if (to.matched.some(record => record.meta.requiresAuth) && !isAuthenticated) {
- next({ name: 'login' });
- } else if (to.name === 'login' && isAuthenticated) {
- next({ name: 'index' });
- } else {
- next();
-
- }
- });
- function checkIfUserIsAuthenticated() {
- // 检查本地存储中的认证状态
- const isAuthenticated = localStorage.getItem('isAuthenticated');
- // 如果认证状态为true,则返回true;否则返回false
- return isAuthenticated === 'true';
- }
- export default router
没有注册userUserStore出现的错误,大概意思就是当前没有组件生产,拿取不到Mian.ts中注册的pinia:
附上mian.ts文件
- import { createApp } from 'vue'
- import './style.css'
- import App from './App.vue'
- import router from "./router";
- import ElementPlus from 'element-plus'
- import * as ElementPlusIconsVue from '@element-plus/icons-vue'
- import 'element-plus/dist/index.css'
- import './assets/css/global.less';
- import { createPinia } from "pinia";
- import bus from "./mitt";
- import useCounterStore from "@/store/user";
- import { storeToRefs } from 'pinia';
- const pinia = createPinia();
-
- const store = useCounterStore()
- const storerefs = storeToRefs(store)
-
- //模拟数据
- import { mockXHR } from "./mock/index";
- mockXHR()
-
- const app = createApp(App)
-
- for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
- app.component(key, component)
- }
-
- app.use(pinia)
- app.use(router)
- app.use(ElementPlus)
-
- //VUE提供了provide 和 inject来解决了这个问题。无论组件层次结构有多深,父组件都可以作为其所有子组件的依赖提供者。
-
- app.provide('store_state', storerefs) //拿取到的pinia的state
- app.provide('store', store) //拿到的整个pinia
- app.provide('bus', bus)
-
- app.mount('#app')
4.菜单文件 nva->index.vue
- <script lang="ts" setup>
- import { onMounted, reactive, ref ,watch,inject} from "vue";
- import { useRoute } from "vue-router";
- import { get } from "../../axios/api";
- import bus from "@/mitt";
- const isCollapse = ref(true);
- const router = useRoute();
- let nowRouter = ref("");
- let NavList = ref([]);
- let childPath = ref([]);
-
- const store = inject('store')
- const store_state = inject('store_state')
-
-
- //监听当前路由信息的变化 newVlaue是新值 ,vlaue 是变化之前的旧值
- watch(()=>store_state.NowRouterPath.value,(newValue,value)=>{
- //判断当前的菜单数据信息中,是否包含新的路由数据,nowRouter赋值为新的路由,nav就会选中高亮显示
- NavList.value.map((item) => {
- newValue.indexOf(item.fullPath) == -1
- ? item.children.map((child: any) => {
- nowRouter.value = newValue;
- router.fullPath.indexOf(newValue) !== -1 ? (nowRouter.value = newValue) : "";
- })
- : "";
- });
- })
-
- onMounted(() => {
- //这个只是判断请求的nav数据是否存在本地中,存在就不请求接口了
- if(sessionStorage.getItem('NavList')){
- NavList.value = JSON.parse(sessionStorage.getItem('NavList'))
- getNowPath()
- }else{
- getNavList()
- }
- });
-
- //函数
-
- const getNavList = ()=>{
- let params = {
- token: localStorage.getItem("token"),
- };
- get("/api/getMenuList", params).then((res) => {
- NavList.value = res.data;
- store.oneSetMenuList(NavList);
- sessionStorage.setItem('NavList',JSON.stringify(NavList.value))
- getNowPath()
- });
- }
- const ClickToGo = (data)=>{
-
- }
-
- const getNowPath = () =>{
- NavList.value.map((item) => {
- item.children.length !== 0
- ? item.children.map((child: any) => {
- childPath.value.push(child.path);
- })
- : childPath.value.push(item.path);
- });
- childPath.value.map((item) => {
- if (router.path.indexOf(item) !== -1) {
- nowRouter.value = item;
- }
- });
- }
- </script>
- <template>
- <el-menu
- class="el-menu-vertical-demo"
- :collapse="store_state.menuiIsCollapse.value"
- :unique-opened="true"
- :router="true" //为true的话,可以根据点击菜单中绑定的index是'/index'定义的路由,可点击直接跳转
- :default-active="nowRouter"
- background-color="#545c64"
- text-color="#fff"
- active-text-color="#ffd04b"
- >
- <template v-for="(item, index) in NavList">
- <el-sub-menu v-if="item.children.length !== 0" :index="item.id">
- <template #title> //下拉菜单
- <el-icon><component :is="item.web_icon" /></el-icon>
- <span>{{ item.title }}</span>
- </template> //点击跳转菜单
- <el-menu-item-group v-for="(children, k) in item.children">
- <el-menu-item :index="children.path" @click="ClickToGo(children)">
- {{ children.title }}</el-menu-item
- >
- </el-menu-item-group>
- </el-sub-menu>
- <el-menu-item v-else :index="item.path">
- <el-icon><component :is="item.web_icon" /></el-icon>
- <template #title>{{ item.title }}</template>
- </el-menu-item>
- </template>
- </el-menu>
- </template>
- <style scoped lang="less">
- </style>
5.tab组件
- <template>
- <div class="container" >
- <el-tabs
- v-model="editableTabsValue"
- type="card"
- closable
- @tab-remove="removeTab"
- @tab-click="getRouter"
- >
- <el-tab-pane
- v-for="(item, index) in editableTabs"
- :key="index"
- :label="item.meta.name"
- :name="item.fullPath"
- >
- </el-tab-pane>
- </el-tabs>
- </div>
- </template>
- <script lang="ts" setup>
- import { defineComponent, ref, onMounted ,inject,watch} from "vue";
- import bus from "@/mitt";
- import { useRouter } from "vue-router";
-
- const store = inject('store')
- const store_state = inject('store_state')
- //直接赋值为当前的路由 editableTabsValue 对应到 el-tab-pane中的:name 如果相同就会自动高亮显示
- let editableTabsValue = store_state.NowRouterPath;
- //pinia中保存的 tabs数据
- const editableTabs = store_state.TabsList
-
- // 页面加载时执行
- onMounted(() => {});
- // 移除选项卡
- const removeTab = (targetName: string) => {};
- // 点击选项卡
- const getRouter = (i: any) => {};
- </script>
6.header 面包屑组件
- <template>
- <div class="header-box">
- <div class="header_item">
-
- <el-breadcrumb separator="/" class="header_left_title">
- <el-breadcrumb-item :to="{ path: '/home' }">主页</el-breadcrumb-item>
- <el-breadcrumb-item>{{ titleList.Pname }}</el-breadcrumb-item>
- <el-breadcrumb-item v-if="titleList.name">{{
- titleList.name
- }}</el-breadcrumb-item>
- </el-breadcrumb>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { onMounted, defineProps, provide, inject ,watchEffect ,watch} from "vue";
- import { useRouter, useRoute } from "vue-router";
- import { ref, reactive } from "vue";
-
- const router = useRoute();
- //面包屑显示数据
- let titleList = reactive({ Pname: "", name: "" });
-
-
- const store = inject('store')
- const store_state = inject('store_state')
-
- onMounted(() => {
- //拿取router 路由信息
- getMenuList(router.path);
- });
-
- //监听当前路由的信息变化
- watch(()=>store_state.NowRouterPath.value,(newValue,value)=>{
- getMenuList(newValue);
- })
-
-
- function getMenuList(path) {
- //path:当前路由 ; 拿到nav菜单数据,对比是否能找到path对应的菜单信息,
- let menuList = JSON.parse(sessionStorage.getItem('NavList'))
- menuList.map((item) => {
- if (item.path !== path) {
- //判断是否存在children 可点击菜单
- item.children.length !== 0
- ? item.children.map((child) => {
- //存入 下拉菜单的名称 和 筛选出的点击菜单名称
- if (child.path == path) {
- titleList.Pname = item.title;
- titleList.name = child.title;
- }
- })
- : "";
- } else {
- titleList.Pname = item.title;
- titleList.name = "";
- }
- });
- }
如有写的不明确的地方可以提出来,或者大佬们有更好的方法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。