前端路由layout布局处理以及菜单交互(三)
上篇介绍了前端项目部署以及基本依赖的应用,这次主要对于路由以及布局进行模块化处理
一、 创建layout模块
1、新建src/layout/index.vue
<template><el-container class="common-layout"><!-- <el-aside class="aside"><Aside/></el-aside> --><el-container><el-header class="header"><Header/></el-header><el-main class="main"><router-view></router-view></el-main><el-footer class="footer">Copyright © 2020 云风网, All rights reserved. 京ICP备20002789号-1</el-footer></el-container></el-container>
</template><script setup lang="ts">
// import Aside from './components/aside.vue'
import Header from './components/header.vue'</script><style lang="scss" scoped>
@import '@/assets/styles/mixins.scss';
.common-layout{width: 100%;height: 100vh;.aside{height: 100vh;width: 200px;}.header{height: 60px;padding: 0;}.main{@include scrollBar;}.footer{height: 60px;background-color: #343a40;color: #fff;line-height: 60px;}
}</style>
2、新建头部组件src/layout/components/header.vue
<template><el-menu:default-active="activeIndex"class="header-container"mode="horizontal":ellipsis="false"@select="handleSelect"><el-menu-item index="0"><imgclass="logo"src="@/assets/logo.svg"alt="logo"/></el-menu-item><navbar-itemv-for="(route, index) in routerList":key="route.path + index":item="route":base-path="route.path":is-nest="false"/></el-menu>
</template><script setup lang="ts">
import NavbarItem from './navbarItem.vue';
import { useRouter} from 'vue-router';
const router = useRouter();const activeIndex = ref('1')
const routerList = router.getRoutes();
console.log('routerList',routerList);
const handleSelect = (key: string, keyPath: string[]) => {console.log(key, keyPath)
}
</script><style lang="scss" scoped>
.el-menu--horizontal > .el-menu-item:nth-child(1) {margin-right: auto;
}
.header-container{height: 100%;padding: 0 50px;background-color: #fff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);.logo{width: 40px;}
}
</style>
3、新建菜单组件src/layout/components/navbarItem.vue
<template><div v-if="!item.hidden"><template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren)"><app-link v-if="onlyOneChild.meta.title" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)"><el-menu-item :index="resolvePath(onlyOneChild.path,'')" @click="handleClick(item.path)"><svg-icon :icon-class="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" /><template #title><span class="menu-title" :title="hasTitle(onlyOneChild.meta.title)">{{ onlyOneChild.meta.title }}</span></template></el-menu-item></app-link></template><el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path,'')" teleported><template v-if="item.meta" #title><svg-icon :icon-class="item.meta && item.meta.icon" /><span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span></template><app-link v-for="child in item.children" :key="child.path" :to="resolvePath(child.path, '')"><el-menu-item:item="child"class="nest-menu"@click="handleClick(child.path)"><template #title><span class="menu-title">{{ child.meta.title }}</span></template></el-menu-item></app-link></el-sub-menu></div></template><script setup lang="ts">import { isExternal } from '@/utils/validate.ts'import AppLink from './Link.vue'import { getNormalPath } from '@/utils/mis'interface MenuItem {path: string;meta?: {icon?: string;title?: string;[key: string]: any;};query?: string;children?: MenuItem[];hidden?: boolean;noShowingChildren?: boolean;}const props = defineProps<{item: MenuItem;isNest: boolean;basePath: string;}>();const onlyOneChild = ref<MenuItem>({ path: '', meta: {} });function hasOneShowingChild(children: MenuItem[] = [], parent: MenuItem): boolean {const showingChildren = children.filter(item => {if (item.hidden) {return false;} else {onlyOneChild.value = item;return true;}});if (showingChildren.length === 1) {return true;}if (showingChildren.length === 0) {onlyOneChild.value = { ...parent, path: '', noShowingChildren: true, meta: {} };return true;}return false;}function handleClick(routePath: string) {localStorage.setItem('routePath', routePath);}function resolvePath(routePath: string, routeQuery?: string) {if (isExternal(routePath)) {return routePath;}if (isExternal(props.basePath)) {return props.basePath;}if (routeQuery) {let query = JSON.parse(routeQuery);return { path: getNormalPath(`${props.basePath}/${routePath}`), query };}return getNormalPath(`${props.basePath}/${routePath}`);}function hasTitle(title: string | undefined): string {return title && title.length > 5 ? title : '';}</script>
4、新建菜单组件src/layout/components/Link.vue
<template><component :is="type" v-bind="linkProps()"><slot /></component>
</template><script setup lang="ts">
import { isExternal } from '@/utils/validate.ts'const props = defineProps({to: {type: [String, Object],required: true}
})const isExt = computed(() => {return isExternal(props.to)
})const type = computed(() => {if (isExt.value) {return 'a'}return 'router-link'
})function linkProps() {if (isExt.value) {return {href: props.to,target: '_blank',rel: 'noopener'}}return {to: props.to}
}
</script>
5、新建方法封装文件src/utils/validate.ts
/*** 判断url是否是http或https * @param {string} path* @returns {Boolean}*/export function isHttp(url) {return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
}/*** 判断path是否为外链* @param {string} path* @returns {Boolean}*/export function isExternal(path) {return /^(https?:|mailto:|tel:)/.test(path)
}/*** @param {string} str* @returns {Boolean}*/
export function validUsername(str) {const valid_map = ['admin', 'editor']return valid_map.indexOf(str.trim()) >= 0
}/*** @param {string} url* @returns {Boolean}*/
export function validURL(url) {const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/return reg.test(url)
}/*** @param {string} str* @returns {Boolean}*/
export function validLowerCase(str) {const reg = /^[a-z]+$/return reg.test(str)
}/*** @param {string} str* @returns {Boolean}*/
export function validUpperCase(str) {const reg = /^[A-Z]+$/return reg.test(str)
}/*** @param {string} str* @returns {Boolean}*/
export function validAlphabets(str) {const reg = /^[A-Za-z]+$/return reg.test(str)
}/*** @param {string} email* @returns {Boolean}*/
export function validEmail(email) {const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/return reg.test(email)
}/*** @param {string} str* @returns {Boolean}*/
export function isString(str) {if (typeof str === 'string' || str instanceof String) {return true}return false
}/*** @param {Array} arg* @returns {Boolean}*/
export function isArray(arg) {if (typeof Array.isArray === 'undefined') {return Object.prototype.toString.call(arg) === '[object Array]'}return Array.isArray(arg)
}
二、修改router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Layout from '@/layout/index.vue'
//公共路由
export const constantRoutes = [{path: '/',component: Layout,redirect: '/home',hidden: false,children: [{path: 'home',name: 'Home',meta:{ title: '系统知识',routerNum: 0},component: () => import('@/views/Home.vue')}]},{path: '/',redirect: "/article",component: Layout,hidden: false,children: [{path: 'article',name: 'Article',meta:{ title: '插件管理',routerNum: 1},component: () => import('@/views/Article.vue')}]},{path: '/',redirect: "/mix",component: Layout,hidden: false,meta:{ title: '多级菜单',routerNum: 0},children: [{path: 'home',name: 'Home',meta:{ title: '系统知识',routerNum: 0},component: () => import('@/views/Home.vue')},{path: 'article',name: 'Article',meta:{ title: '插件管理',routerNum: 1},component: () => import('@/views/Article.vue')}]},// {// path: '/article/:id',// name: 'Article',// meta:{ title: '插件管理',routerNum: 1},// component: () => import('@/views/Article.vue')// }
]
const router = createRouter({history: createWebHistory(),routes: constantRoutes
})export default router
相关文章:

前端路由layout布局处理以及菜单交互(三)
上篇介绍了前端项目部署以及基本依赖的应用,这次主要对于路由以及布局进行模块化处理 一、 创建layout模块 1、新建src/layout/index.vue <template><el-container class"common-layout"><!-- <el-aside class"aside">&l…...
小结:DNS,HTTP,SMTP,IMAP,FTP,Telnet,TCP,ARP,ICMP
DNS(Domain Name System,域名系统) 是互联网的重要组成部分,它负责将人类易读的域名(如 www.google.com)转换为机器可以识别的 IP 地址(如 142.250.72.206)。这一过程被称为域名解析…...

【C++】P2550 [AHOI2001] 彩票摇奖
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述输入格式:输出格式:输入输出样例: 💯题解思路1. 问题解析 💯我的实现实现逻辑问题分析 💯老…...

并发服务器框架——zinx
zinx框架 Zinx 是一个用 Go 语言编写的高性能、轻量级的 TCP 服务器框架,它被设计为简单、快速且易于使用。Zinx 提供了一系列的功能,包括但不限于连接管理、数据编解码、业务处理、负载均衡等,适用于构建各种 TCP 网络服务,如游戏…...

Unity 中计算射线和平面相交距离的原理
有此方法 能够计算射线和平面是否相交以及射线起点到平面交点的距离 代码分析 var dot Vector3.Dot(ray.direction, plane.normal);计算射线和平面法线的点积,如果大于等于0,则说明射线和平面没有相交,否则,说明射线和平面相交…...
浅谈棋牌游戏开发流程七:反外挂与安全体系——守护游戏公平与玩家体验
一、前言:为什么反外挂与安全这么重要? 对于任何一款线上棋牌游戏而言,公平性和玩家安全都是最重要的核心要素之一。如果游戏环境充斥着各式各样的外挂、作弊方式,不仅会毁坏玩家体验,更会导致游戏生态崩塌、口碑下滑…...

《无力逃脱》V1.0.15.920(59069)官方中文版
艾丹是一名三臂赏金猎人,他必须追捕银河系中最危险、最难以捉摸的割喉者。 有些悬赏是金钱,有些则是有价值的信息。艾丹可以利用这些信息找到让他走上这条路的人,同时也会卷入一个全银河系的阴谋中。 拥有三条手臂可以让你同时对付更多的敌…...
六种主流服务器的选择与使用
网络的运行离不开各种服务器,它们各司其职,为我们提供稳定的网络服务。本文带大家了解6种常见服务器类型。 服务器的六大种类 第一种:Web服务器 Web服务器是互联网的核心。当你打开一个网站,比如百度或淘宝,浏览器会…...
TiDB 升级至高版本提示'mysql.tidb_runaway_watch' doesn't exist 问题处理
作者: asd80703406 原文来源: https://tidb.net/blog/90394c97 背景 近期发现很多人从低版本升级至TiDB v7 或者v8版本,均遇到了tidb-server启动失败,提示报错如下: ["get runaway watch record failed"…...

GRU-PFG:利用图神经网络从股票因子中提取股票间相关性
“GRU-PFG: Extract Inter-Stock Correlation from Stock Factors with Graph Neural Network” 论文地址:https://arxiv.org/pdf/2411.18997 摘要 股票预测模型可以分为两个主要类别:第一类,例如GRU和ALSTM,这些模型仅基于股票…...

数字化供应链创新解决方案在零售行业的应用研究——以开源AI智能名片S2B2C商城小程序为例
摘要: 在数字化转型的浪潮中,零售行业正经历着前所未有的变革。特别是在供应链管理方面,线上线下融合、数据孤岛、消费者需求多样化等问题日益凸显,对零售企业的运营效率与市场竞争力构成了严峻挑战。本文深入探讨了零售行业供应…...
安卓Activity执行finish后onNewIntent也执行了
测试反应投屏时下一集可能播放不成功。 首先看一下日志: onCompletion onCast handlerMessage: 2 finish: PlayerActivityabc7fdc onPause: PlayerActivityabc7fdc onNewIntent: PlayerActivityabc7fdc onResume: PlayerActivityabc7fdc onPause: PlayerActivityab…...

数据结构.期末复习.学习笔记(c语言)
《数据结构》复习概要 一、概论 二、基础1. 基本概念2. 四种逻辑结构及特点3. 算法的概念、特性4. 算法设计的4个要求 三、线性结构1.顺序表2.单链表3.循环链表双向链表4.栈(后进先出)5.队列(先进先出) 四、树和二叉树1.树2.二叉…...

Kafaka安装与启动教程
1.下载 先去官网Apache Kafka可以查看到每个版本的发布时间。选择你要安装的版本。 然后进入linux建立要存放的文件夹,用wget命令下载 2.安装 先解压缩: tar -xvzf kafka_2.12-3.5.1.tgz -C ../ 3.配置文件 修改server.properties: cd .…...
根据docker file 编译镜像
比如给到一个Dockerfile 第一步编译镜像 cd /path/to/Dockerfiledocker build -t <DOCKER_IMAGE_NAME> . build 命令编译镜像 -t 镜像名字 . 指dockerfile 所在目录 如果遇到报错 [] Building 0.3s (3/3) FINISHED …...
联邦学习的 AI 大模型微调中,加性、选择性、重参数化和混合微调
联邦学习的 AI 大模型微调中,加性、选择性、重参数化和混合微调 在联邦学习的 AI 大模型微调中,加性、选择性、重参数化和混合微调是不同的操作方式,具体如下: 加性微调 定义与原理:加性微调是在原始模型的基础上添加额外的可训练参数来进行模型调整。这种方式不会改变原…...

android 外挂modem模块实现Telephony相关功能(上网,发短信,打电话)
一.背景 当前模块不支持Telephony相关的功能,例如上网、发短信等功能,就需要外挂另一个模块实现此功能,这就是外挂modem模块实现Telephony功能,此篇主要就是说实现外挂modem模块功能中的Framework层实现逻辑,如下流程是在Android 13中实现的外挂pcie模块的流程 二.ril库相…...

【计算机视觉技术 - 人脸生成】2.GAN网络的构建和训练
GAN 是一种常用的优秀的图像生成模型。我们使用了支持条件生成的 cGAN。下面介绍简单 cGAN 模型的构建以及训练过程。 2.1 在 model 文件夹中新建 nets.py 文件 import torch import torch.nn as nn# 生成器类 class Generator(nn.Module):def __init__(self, nz100, nc3, n…...

数据中台与数据治理服务方案[50页PPT]
本文概述了数据中台与数据治理服务方案的核心要点。数据中台作为政务服务数据化的核心,通过整合各部门业务系统数据,进行建模与加工,以新数据驱动政府管理效率提升与政务服务能力增强。数据治理则聚焦于解决整体架构问题,确保数据…...

【Qt】将控件均匀分布到圆环上
1. 关键代码 for(int i0; i<10; i){/*m_panLabelIcon - 大圆环控件m_slotsIcon[i] - 小圆控件*/QString idxStr QString::number(i1);m_slotsIcon[i] new QLabel(m_panLabelIcon);m_slotsIcon[i]->setFont(ftSlot);m_slotsIcon[i]->setText(idxStr);m_slotsIcon[i]-…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Java求职者面试指南:计算机基础与源码原理深度解析
Java求职者面试指南:计算机基础与源码原理深度解析 第一轮提问:基础概念问题 1. 请解释什么是进程和线程的区别? 面试官:进程是程序的一次执行过程,是系统进行资源分配和调度的基本单位;而线程是进程中的…...