vue动态标签路由跳转
长话短说,这里的路由的就是实现各个网页跳转的一个关键组件,下面我们来一步一步地解析一下路由的使用过程。
创建路由
首先我们在src文件夹下的router的
index.js
中创建我们需要的路由路径。话不多说我们这就在
index.js
中开写!!首先我们先引入必须的组件:
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Index from '../views/index.vue'
其中
import { createRouter, createWebHistory } from 'vue-router'
是不变的官方给的创建路由的组件,而HomeView
、Index
则是我们手动创建的组件,相信大家从from
关键字后面的路径名称也能够看出来。接下来我们就来创建一个路由吧~~
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
})
这个
history
创建了一个基于 HTML5 History API 的路由历史对象。这种类型的历史对象允许你构建一个单页应用程序(SPA),其中页面的导航不会导致页面重新加载,但是可以改变 URL 并允许用户通过浏览器的前进和后退按钮来导航。而其中的
import.meta.env.BASE_URL
就是指定了根路径,根路径的默认值为/
,看到/
是不是突然就顿悟了??没错,我们的项目的主页路径http://localhost:5174/
除去默认的http://localhost:5174
之后那最后的/
不就是我们import.meta.env.BASE_URL
产生的嘛。换句话来说这段代码产生我们默认
的首页路径。既然我们首页路径都有了,那我们后续的网页路径不就在首页路径后面添加不就成啦?说干就干。我们继续来写~
const router = createRouter({
routes:[
{
path: '/',
name: 'Index',
component: Index,
children: [
{
path: '/home/index',
name: 'index',
meta: { title: '首页' },
component: () => import("../views/home/index.vue")
},
}
]
})
上面这段代码就是在定义我们页面跳转路径和对应要跳转的组件名称了,上面这段长的其实最有用的就俩句代码:
path: '/',
component: Index,
},
是的,我们要有有路由的路径以及要跳转的组件名称,那就足够了,至于其余的无伤大雅。
好,我们接着讲这个
children
是咋回事,我们直接翻译过来我们也大致可以猜出来了,children
的意思是儿童,那不就是说是我们当前路由的一个子类嘛~。那我们当前处于/
的路径状态下,那我们子类里面写了路径path: '/home/index'
不就是说我们的子网页的路径为:/home/index
嘛,对应跳转的组件则为../views/home/index.vue
里面的网页。到这里就懂了吧?这些懂了就可以了,我们创建路由的事情就完成了。哦对了,我们最后要我们的router
常量给export
出去方便其余页面调用。
export default router
其余的部分按照上面的思路来就好了,接下来展示一下完整的代码:
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Index from '../views/index.vue'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'Index',
component: Index,
children: [
{
path: '/home/index',
name: 'index',
meta: { title: '首页' },
component: () => import("../views/home/index.vue")
},
{
path: '/system',
name: 'system',
meta: { title: '系统管理' },
children: [
{
path: '/system/log',
name: 'log',
meta: { title: '系统日志' },
component: () => import("../views/system/log.vue")
}
]
},
{
path: '/user',
name: 'user',
meta: { title: '员工同事' },
children: [
{
path: '/user/index',
name: 'userindex',
meta: { title: '员工管理' },
component: () => import("../views/user/index.vue")
}
]
},
{
path: '/attendance',
name: 'attendance',
meta: {
title: '考情统计'
},
children: [
{
path: '/attendance/info',
name: 'attendanceindex',
meta: { title: '个人考情' },
component:()=>import("../views/info.vue")
}
]
},
{
path: '/device',
name: 'device',
meta: { title: '设备管理' },
children: [
{
path: '/device/index',
name: 'deviceinfo',
meta: { title: '正在运行' },
component:()=>import("../views/device/index.vue")
}
]
},
{
path: '/material',
name: 'material',
meta: { title: '物料管理' },
children: [
{
path: '/material/index',
name: 'materialinfo',
meta: { title: '正在运行' },
component:()=>import("../views/material/index.vue")
}
]
},
{
path: '/productoutbound',
name: 'productoutbound',
meta: { title: '产品数据' },
children: [
{
path: '/productoutbound/index',
name: 'productoutboundinfo',
meta: { title: '产品出库' },
component: () => import("../views/productoutbound/index.vue")
},
{
path: '/productoutbound/info',
name: 'productqualityinspection',
meta: { title: '产品质检' },
component:() => import("../views/productoutbound/info.vue")
}
]
},
{
path: '/analyse/info',
name: 'Promotion',
meta: { title: '统计分析' },
component: () => import("../views/analyse/index.vue")
},
]
}
]
})
export default router
注册路由
注册路由很简单,我们路由创建好了之后总得让系统知道咱们在哪吧?欸,这时候我们在vue自带的文件
main.js
上写入:
import router from './router'
const app = createApp(App)
app.use(router)
上面的
./router
代表了我们刚刚上面创建路由导出的常量router
的路径,然后我们使用vue框架自带的app.user(router)
即可。这里app是干啥的就不讲了,大家去看看官网文档啥的,这个我的理解是和.NET里面的那个builder
差不多的。
使用路由
接下来我们将通过一个for循环和结合我们的Element-plus UI框架来动态地加载我们的路由,实现效果图如下图所示:
接下来我们在将在components文件夹下创建组件
navMenu.vue
、navItem.vue
。其中
navMenu.vue
封装了我们上图左侧导航栏部分的框架,也就是准备工作,而navItem.vue
才是真正用for循环去实现导航栏具体内容部分。知道了这俩组件的作用,那我们话不多说直接开动!
实现navMenu.vue组件
首先是我们的
navMenu.vue
组件部分,这个肯定是得先写的,咱们得把大体框架写好才能继续下一步嘛~
<template>
<el-aside width="200px" class="aside">
<el-menu >
<el-menu-item >
<el-image />
</el-menu-item>
<NavItem />
</el-menu>
</el-aside>
</template>
为了方便讲解,我剥离了大部分属于美观部分的代码,剩下一个框架部分的代码,我认为这个组件的核心部分应该是这个框架部分,懂了框架部分精华部分就学到了。接下来我们来逐步讲解一下。
首先最外层这个组件用一个
组件包起来了,这里我们可以理解为这个组件就代表了整个我们的导航栏。
可以看到我们导航栏分成了图片log部分和具体的功能部分,所以我们又把整个导航分成了
和 ,图片log内容我们封装在了 ,而具体的功能按钮我们则封装在了 里面。 那我怎么知道我们遍历出来的
里面的每个导航按钮名字是我们所需要的呢?我们总得把对应的按钮名字和按钮路径传给给 组件才行吧?那既然如此我们在 navMenu.vue
组件部分还得干一件事,我们得把每个导航按钮的名字和路径都给定义一下,那话不多说我们直接开干~~
<script setup>
import { reactive } from 'vue'
const items = reactive([
{
text: '首页',
url: '/home/index',
icon: 'HomeFilled'
},
{
text: '系统管理',
url: '/system',
icon: 'Grid',
child: [
{ text: '系统日志', url: '/system/log', icon: 'Setting' }
]
},
{
text: '员工同事',
url: '/user',
icon: 'Avatar',
child: [
{ text: '员工管理', url: '/user/index', icon: 'User' }
]
},
{
text: '考勤统计',
url: '',
icon: 'StarFilled',
child: [
{ text: '个人考勤', url: '/attendance/info', icon: 'User' },
{ text: '考勤分析', url: '/attendance/analyse', icon: 'More' },
]
},
{
text: '设备管理',
url: '/device',
icon: 'HelpFilled',
child: [
{ text: '正在运行', url: '/device/index', icon: 'Tools' }
]
},
{
text: '物料管理',
url: '/material',
icon: 'Share',
child: [
{ text: '物料仓库', url: '/material/index', icon: 'Share' }
]
},
{
text: '产品数据',
url: '/Promotion',
icon: 'Promotion',
child: [
{ text: '产品出库', url: '/productoutbound/index', icon: 'Promotion' },
{ text: '产品质检', url: '/productoutbound/info', icon: 'Promotion' }
]
},
{
text: '统计分析',
url: '/analyse/info',
icon: 'VideoCameraFilled'
}
])
</script>
这里解释下我们引入
reactive
函数的作用,这个函数的作用在于假如我们items里面的内容在运行过程改变了,那么reactive函数会保证后续其余调用了我们items部分的内容同步更新。那有人说这有啥用,我们导航栏内容肯定不变的,要改变我们直接改代码就好了呀。是的这句话的确没错,但是我们要考虑的全面一点,假如我们导航栏的内容显示是根据用户权限来的呢?系统管理的内容权限肯定要比普通用户多呀,此时我们reactive就可以保证我们系统权限变成管理员的时候对应导航栏的内容也同步改变。我们items常量其实就是一个数组,每个列表
{}
封装一个导航栏内容,导航栏内容由text
、url
、icon
组成。text则显示导航栏按钮的名字,url则是对应导航栏所要跳转的路径,icon则是导航栏按钮的图标log。至此一切基础准备已经就绪了,接下来我将对应的数据填入
<template>
部分:
<template>
<el-aside width="200px" class="aside">
<el-menu :default-active="route.path" exact class="el-menu-vertical-demo" router>
<el-menu-item>
<el-image />
</el-menu-item>
<NavItem v-for="v in items" :key="v.url" :item="v" :basePath="v.url" />
</el-menu>
</el-aside>
</template>
这里核心部分就是一个
<el-menu :default-active="route.path" exact class="el-menu-vertical-demo" router>
和<NavItem v-for="v in items" :key="v.url" :item="v" :basePath="v.url" />
其中
<el-menu :default-active="route.path" exact class="el-menu-vertical-demo" router>
的参数:
-
default-active="route.path"
:本质是一个动态绑定属性,它的作用是设置菜单(Menu)组件当前激活的菜单项。这里绑定的
route.path
通常来自Vue Router,表示当前路由的路径。这样设置可以确保当前访问的路由对应的菜单项被高亮显示。 -
exact:
在 Vue.js 的
el-menu
组件中,exact
属性用于控制路由的激活状态。具体来说,exact
属性确保只有当路由路径与菜单项的index
完全匹配时,该菜单项才会被激活。默认情况下,Vue Router 的路由匹配是基于前缀的。这意味着如果当前路由是
/home
,那么所有以/home
开头的路由(例如/home/index
)都会被认为是匹配的。这可能导致多个菜单项同时被激活。通过设置
exact
属性,你可以确保只有当路由路径与菜单项的index
完全匹配时,该菜单项才会被激活。这对于避免多个菜单项同时被激活的情况非常有用。 -
router
router
属性用于启用菜单项与 Vue Router 的集成,使得菜单项可以作为导航链接使用,简单来说就是告诉菜单我是通过路由进行跳转的。以下是详细解释:
- 当
el-menu
组件设置了router
属性后,每个el-menu-item
的index
属性会被视为一个路由路径。 - 当用户点击某个
el-menu-item
时,el-menu
组件会自动调用 Vue Router 的导航功能,将应用导航到index
属性指定的路径。
- 当
第一个重点我们就讲完了,接下来我们讲解一下
<NavItem v-for="v in items" :key="v.url" :item="v" :basePath="v.url" />
,先说明一下,这里的<NavItem />
可不是vue框架自带的一个组件哦~这个其实就是咱们的navItem.vue
组件,我们通过`import xxx from xx将其导入:
<script setup>
import { reactive } from 'vue'
import { useRouter, useRoute } from "vue-router"; //导入路由
import NavItem from './navItem.vue' //子组件
import langlangfactoryImage from '../assets/images/langlangfactory.png'
const route = useRoute();
</script>
oh~忘记讲了,我们上面
<el-menu :default-active="route.path" exact class="el-menu-vertical-demo" router>
用到的router属性也算从上面这段代码里面导入的哦~~我们继续讲解
<NavItem v-for="v in items" :key="v.url" :item="v" :basePath="v.url" />
,
-
v-for="v in items"
这里我们通过v-for 进行遍历items,这个items就是我们上面定义的数组,以每个
{}
为单位作为一个v
传给组件。 -
:key="v.url"
:key是vue自带的一个属性,它的主要作用是帮助 Vue 识别和跟踪每个节点的唯一性。当列表数据发生变化时,Vue 会根据
key
属性来重新排列元素,以确保 DOM 更新尽可能高效。例如:一个列表从[A, B, C]
变为[B, A, C]
,Vue 会根据key
值来移动A
和B
的位置,而不是重新创建它们。 -
:item="v" :basePath="v.url"
这个item 和basePath就不同于key了,这俩是我们自己创建的遍历,item存储我们遍历出来items数组里面的{}数据,basePath存储{}里面的url字段的内容,也就是我们导航按钮的路由路径。
到这里我们
navMenu.vue
组件的按钮我们就讲解结束了,接下来我们讲解navItem.vue
的组件内容,也就是我们要正式去实现我们的组件啦!!!
实现navItem.vue组件
首先明确我们
navItem.vue
组件的作用,其作用就是实现具体的导航按钮的加载,我们再来回顾一下我们的导航栏效果吧~
发现没有,我们导航栏有些只有一个单独一个导航按钮,有些则是导航按钮下面还有一个子按钮,这就说明了,我们
navItem.vue
里面要分成有子级导航按钮和无子级导航按钮的区别,所以我们代码如下:
<template>
<!-- 无子级 -->
<el-menu-item :index="basePath" v-if="!item.child || item.child.length <= 0">
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.text }}</span>
</el-menu-item>
<!-- 有子级 -->
<el-sub-menu :index="basePath" v-else>
<template #title>
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.text }}</span>
</template>
<NavItem v-for="sub in item.child" :key="sub.url" :item="sub" :basePath="sub.url" />
</el-sub-menu>
</template>
<script setup>
import { ref, reactive } from 'vue'
const { item, basePath } = defineProps({
item: {
type: Object,
},
basePath: {
type: String
}
})
这里的代码我依旧是剥离了一些美化样式的代码,只保留的核心的代码,这样可以看的更加清晰一点,更加能够把握住重点。
在此之前我们要介绍一下
<script setup>
部分的代码的,这里我们用defineProps
函数引入了item
和basePath
,这个defineProps
的作用其实就是类似于定义了一个构造函数,里面接收了item
和basePath
这俩参数,这俩参数从何而来呢?这俩参数当然是我们在前面navMenu.vue
组件中 使用<NavItem v-for="v in items" :key="v.url" :item="v" :basePath="v.url" />
传给当前组件navItem.vue
的呀,这样我们在navItem.vue
就能使用那些在navMenu.vue
中传入的数据了。回到我们
navItem.vue
的代码呢,首先我们是利用了v-if
和v-else
去判定我们的导航按钮是否有子级,这里的v-if
和v-else
和我们普通的if语句其实是一样的,当我们不满足v-if="!item.child || item.child.length <= 0"
的时候也就是说我们当前的导航栏按钮无子级的时候我们执行下面v-else
那条语句,否则我们执行v-if
这条语句。接下来我们介绍一下上面我们代码用到的
<el-menu-item />
和
-
`
这个就是无子级导航菜单的实现,他的内容部分你直接给其写上标签名词和图片log即可。
<el-menu-item :index="basePath" v-if="!item.child || item.child.length <= 0"> <el-icon> <component :is="item.icon"></component> </el-icon> <span>{{ item.text }}</span> </el-menu-item>
这里的
index="basePath"
还是一样的,就是为了当路由路径与菜单项的index
完全匹配时,该菜单项才会被激活,主打的一个就是告诉路由器我要去basePath
这个路径,但是得等路由器确认它能够到达才可以。 -
这个呢就是有子级导航菜单的实现组件,这个你可以把他分为两个部分,一个部分是标题,另一个部分是内容。下面我来用一幅图来解释一下它的这俩的组成。
上图就是一个有子级标题的导航栏,现在你是不是一目了然了?对应子级导航菜单来说父级的按钮就是标题,子级部分的按钮就是内容。
那么直接来看这部分的代码:
<template #title>
<el-icon>
<component :is="item.icon"></component>
</el-icon>
<span>{{ item.text }}</span>
</template>
以上是标题部分的代码,这里的
#title
是必须添加的,这是内置的一个参数,用于将item那些参数传给标题,这样就能调用上面的item.icon
和item.text
了,否则是无法调用的。
<NavItem v-for="sub in item.child" :key="sub.url" :item="sub" :basePath="sub.url" />
这部分则是内容部分,采用了递归调用自身的方式来加载出我们的子导航栏,这个
就是当前组件的名字 navItem.vue
,因为window系统是不区别小写的,所以写成和 是一样的。这样调用自身之后再进行渲染以实现子导航栏的出现。 这种操作是不是非常秒呢,如果不懂这个点,仔细想想递归算法的作用,然后代入试一下你就明白啦~~。
到这里我们总结一下路由router和:index的作用
-
:index
显示网页中的url路径,也就是说:index决定的以下这一部分能被我们肉眼看见的路径,但是到底能不能去这个网页不清楚,这个得看router的脸色。
-
router
当得知
:index
想要去上图路径的时候,它会去看看创建路由的时候列表(一开始我们router文件夹里面的index.js的内容)到底有没有我们上图对应的路径,如果是有的,那直接跳转到对应的页面,如果没有那啥也不显示。
以上就是本人对vue框架路由跳转组件的学习理解,如有错误请多包涵~~~~。
停留在世界边缘,与之惜别