1. 引言
我们上次说过,Vue框架实现的是单页应用,整个项目只有一个html文件,我们在vue文件中写代码片段然后引入html页面中展示。但一个真正的项目不会只有一个页面的,在原生js中我们通过写很多份html文件来实现页面跳转,那在Vue里面怎么实现呢?
思维活跃的朋友可能就会想到,我写很多个代码片段,将这个代码片段作为首页,将那个代码片段作为登录。当我点首页的时候就把首页的代码片段拿来展示,登录的代码片段就不展示。其实这样是可以的,实现了页面的跳转。但我们说,一个页面一定是和一个url强绑定的,意思就是当我点击首页,url就会加上‘/index’然后给我跳转到首页的界面,每一个页面都有自己对应的url。我们观察一个网站能发现其实它就是这样做的。如果我们按第一种方法来做,那至始至终都只有一个url,只是代码片段切换了,这样做就不方便了,当我们想为别人展示我们网站的一个页面时,我们还得从最开始的那个状态然后去展示代码片段。而一个页面对于一个url的话,我们只要正确输入页面所对应的url就能去到这个页面。
所以说了这么一大堆,怎么才能实现一个页面对于一个url呢?那就轮到我们今天的主角:Vue-Router 闪亮登场了。
2. Vue-Router
我们还是使用vite这个小工具来创建我们的项目,我们就能得到这样一个目录结构:
我们可以去Vue-Router的官方文档上看看如何使用。Vue-Router
我们在终端中输入以下指令进行安装:
npm install vue-router@4
我们来实现一个后台管理系统的小demo,这个demo功能和界面非常简陋,主要只是为了展示页面跳转的效果。
第一个页面我们就写一个登录页面,login。当用户输入账号和密码时就跳转到首页,也就是home页面。实现一个跳转效果,并且url也要改变。
所以,我们在src下新建一个views文件夹,我们把这个项目中所有的页面写到这个文件夹下。我们创建一个Login.vue, 我们就将这个代码片段作为登录页面,我们先简单的写上:
<template>
<div>
<h1>login page</h1>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped>
</style>
我们希望在页面上看到‘login page’,按照我们之前的写法,就是将它写成一个组件,然后引入到App.vue中。但在这里,我们要将它作为一个页面来展示,就需要为它配一个路由。
那我们再来到src文件夹下新建一个router文件夹,在router文件夹下新建一个index.js文件,在这里来进行路由的配置。
现在目录结构就长这样:
好,来到index.js文件中,我们已经安装了Vue-Router了,那应该怎么为Login.vue配置一个路由呢?
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
export default router;
我们需要先从vue-router中引入两个函数 createRouter, createWebHistory。createRouter函数的调用可以创建一个路由的实例对象,这个函数接收一个对象作为参数,我们要放上两个属性:history和routes,routes的值是一个数组,需要我们自己创建,最后我们将这个router抛出。
我们就在数组routes中进行路由的配置,我们在这个数组中放一个对象。
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const routes = [
{
path: '/login',
component: Login
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
export default router;
这个对象我们放两个属性 path和component。path就是这个页面所拥有的url,component就应该是我们写的那个login页面了,于是我们要将Login.vue引入,import Login from '../views/Login.vue'。这样当浏览器读到了'/login'路径时,它就会将Login组件加载出来,也就是我们写的login页面。
那这样就搞定了吗?还没有,这个文件只是router文件夹下的一个文件,它并没有和其它东西产生关联。我们知道,我们是将App.vue里的东西拿到html文件中进行展示了,而我们是在main.js中完成这个操作的。所以在这里我们抛出了一个router,我们来到main.js中接收它。
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './router/index.js'
createApp(App).use(router).mount('#app')
引入之后我们就要在createApp(App)后面接‘.use(router)’去使用,这样就是App使用了router,配置了路由。这样还没完,我们还需要指明Login加载到哪里,因为是App.vue里的东西会被拿到页面中展示,所以我们还要在App.vue中这样干:
<template>
<div>
<router-view></router-view>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped></style>
现在,我们写的这个Login.vue就是一个页面了,它已经配好了路由,它会有自己对应的url。当我们输入这个url,就能跳转到这个页面。
好,现在我们已经为这个页面配好了路由,接下来,就该实现我们的登录功能了。
html和css部分比较简单,我们直接跳过,我们主要来看js部分。
<template>
<div class="login">
<h2>旅梦的后台管理系统</h2>
<div class="login-box">
<input type="text">
<input type="text">
<button>登陆</button>
</div>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped>
.login {
width: 400px;
border: 1px solid #000;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.login-box {
display: flex;
flex-direction: column;
align-items: center;
}
.login-box input {
margin: 10px 0;
padding: 5px 10px;
}
.login-box button {
padding: 5px 20px;
}
</style>
页面现在就长这样:
我们希望当用户输入正确的账号和密码时,点击登录就会跳转到首页,也就是home页面。
我们需要获取用户在input框输入的内容,可以使用v-model,并且要为button绑定一个点击事件。这里我们就写简单一点,我们直接对用户的输入进行判断。当用户输入admin和123时,我们就进行跳转。
<template>
<div class="login">
<h2>旅梦的后台管理系统</h2>
<div class="login-box">
<input type="text" v-model="username">
<input type="text" v-model="password">
<button @click="login">登陆</button>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
const username = ref("admin");
const password = ref("123");
const login = () => {
if (username.value === 'admin' && password.value === '123') {
// 修改 url 地址栏为 /home
}
}
</script>
<style lang="css" scoped>
.login {
width: 400px;
border: 1px solid #000;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.login-box {
display: flex;
flex-direction: column;
align-items: center;
}
.login-box input {
margin: 10px 0;
padding: 5px 10px;
}
.login-box button {
padding: 5px 20px;
}
</style>
我们将username和password设置了响应式,使用了ref,所以我们想使用它们的值就必须加 ‘.value'。这里我们可以直接就让username和password为admin和123,省的我们每次去输入。然后在login函数中进行判断,当用户输入admin和123时,就要进行页面的跳转,也就是要修改 url 地址栏为 /home。那怎么去修改呢?
我们需要从vue-router中引入一个函数useRouter,调用它创建一个实例对象router。请注意。这里是一个单例模式,也就是说,这个router和index.js中的router是同一个。然后router身上有一个方法push,我们就这样修改url。
<template>
<div class="login">
<h2>旅梦的后台管理系统</h2>
<div class="login-box">
<input type="text" v-model="username">
<input type="text" v-model="password">
<button @click="login">登陆</button>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { useRouter } from "vue-router";
const username = ref("admin");
const password = ref("123");
const router = useRouter()
const login = () => {
if (username.value === 'admin' && password.value === '123') {
// 修改 url 地址栏为 /home
router.push({ path: '/home'});
}
}
</script>
<style lang="css" scoped>
.login {
width: 400px;
border: 1px solid #000;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.login-box {
display: flex;
flex-direction: column;
align-items: center;
}
.login-box input {
margin: 10px 0;
padding: 5px 10px;
}
.login-box button {
padding: 5px 20px;
}
</style>
push方法接收一个对象,里面放上一个属性path为'/home'。此时,当我们点击登录按钮时,浏览器就会跳转到home页面,虽然此时我们还没有写home页面。我们来看一下有没有这个效果。
浏览器的url栏确实跳转到了'/home',这样就可以实现页面的跳转。
接下来,我们就该着手去写home页面,并为它配一个路由,url就要为'/home'。
我们还是来到views文件夹下,创建一个Home.vue文件。
<template>
<div>
<h1>home page</h1>
</div>
</template>
<script setup>
</script>
<style lang="css" scoped>
</style>
先写上一点东西,home page。现在我们就希望,当url为'/home',这个home page能在页面中展示。于是我们就得为它配一个路由,我们来到index.js文件下,为它配一个路由。
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const routes = [
{
path: '/login',
component: Login
},
{
path: '/home',
component: () => import('../views/Home.vue'),
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
export default router;
我们直接在数组中再加一项,就和第一项一样,我们还可以简写一下,直接在component中引入Home.vue。这样写有一个好处,当我们将引入语句全部写在开头时,一打开页面就会全部开始加载,而这样写,只有来到'/home'下才开始加载,分担一下压力。
这样我们就为home页面配好了一个路由,我们来看看效果。
实现了我们想要的效果。那我们就开始写home页面。
<template>
<div class="home">
<div class="head">
<div class="logo">旅梦的后台管理系统</div>
<div class="user">
<span>Welcome, {{ route.query.name }}</span>
</div>
</div>
<div class="main">
<div class="menu">
<ul>
<li>
<router-link to="/home/user">用户管理</router-link>
</li>
<li>
<router-link to="/article">文章管理</router-link>
</li>
<li>
<router-link to="/catgory">评论管理</router-link>
</li>
</ul>
</div>
<div class="content">
</div>
</div>
</div>
</template>
<script setup>
import { useRoute } from 'vue-router';
const route = useRoute();
</script>
<style lang="css" scoped>
.head {
height: 60px;
display: flex;
justify-content: space-between;
padding: 0 30px;
align-items: center;
background-color: #4e12d871;
color: #fff;
}
.main {
display: flex;
height: calc(100vh - 60px)
}
.menu {
flex: 0 0 200px;
/* 不放大 不缩小 */
background-color: #6453e8;
}
.menu ul {
list-style: none;
text-align: center;
}
.menu ul li a {
display: block;
padding: 15px 0;
color: #fff;
cursor: pointer;
}
.content {
flex: 1
}
</style>
我们在span标签中写了Welcome, {{ route.query.name }},这是干嘛的呢?其实这样写能实现一个效果,当用户是admin时,我们就欢迎admin;当用户是张三时,我们就欢迎张三。那怎么去获取这个用户名呢?用户名是在Login.vue中的,我们需要在Home.vue也使用它。
我们可以这样引入,在Login.vue中修改url时,再加上一个query,里面放上一个对象,里面放上一个属性name,这个属性名可以自己取,然后值为username.value。
const login = () => {
if (username.value === 'admin' && password.value === '123') {
// 修改 url 地址栏为 /home
router.push({ path: '/home', query: { name: username.value } });
}
}
这样当我们跳转到 '/home'时,就能带过去一个值。它会被拼接在url上。
这样我们就能实现从其它页面引入一个值放到这个页面来使用。那怎么使用这个值呢?
我们需要从vue-router中引入一个函数useRoute,调用它创建一个实例对象route。
import { useRoute } from 'vue-router';
const route = useRoute();
注意这里和Login.vue中的区别。我们在Login.vue中是使用了useRouter创建了router,这里是使用了useRoute创建了一个route,少了一个'r'你发现没有。这里很容易搞混。引入完之后,我们就可以route.query.name去使用这个值了,我们将它放在span标签里。
现在页面就长这样,右上角欢迎就能欢迎在login页面输入的用户名:
我们还有一种方法能从其它页面带一个值过来,简单提一下。我们这样写:
const login = () => {
if (username.value === 'admin' && password.value === '123') {
// 修改 url 地址栏为 /home
//router.push({ path: '/home', query: { name: username.value } });
router.push({ name: 'Home', params: { name: username.value } });
}
}
使用name和params。这样写的话,当我们在配置路由时还要增加一个属性name:
在index.js中:
const routes = [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/home/:name',
name: 'Home',
component: () => import('../views/Home.vue'),
}
]
并且还要在path中这样写:'/home/:name',允许它带一个参数过来。这样我们也从Login.vue引入了一个值过来,此时我们就要这样使用:route.params.name。这里我们简单提一下。
这里我们还是使用第一种方法。
还是回到这个home页面上:
当我们点击左边用户管理、文章管理和评论管理时,也应该去到各自的页面,那就也要修改url地址,就可以使用router-link标签,然后在to中写对应的路径。
<ul>
<li>
<router-link to="/home/user">用户管理</router-link>
</li>
<li>
<router-link to="/article">文章管理</router-link>
</li>
<li>
<router-link to="/catgory">评论管理</router-link>
</li>
</ul>
其实router-link标签就是封装了a标签给我们使用。这样当我们点击用户管理时,也能去修改url了。
这样也就能实现页面的跳转。但在这里,按照一个通常的后台管理系统来说,当我们点击用户管理时,内容应该出现在右边的白色区别吧。也就是什么意思呢,如果它是跳转到另一个页面了。这个组件就是加载到App.vue中去了。但这里我们想把用户管理这个组件加载到Home.vue中,于是也要为用户管理页面配一个路由,此时就是要在'/home'路径下配一个子路由了。
我们先来到views文件夹下创建一个User.vue文件,用它来作为用户管理的页面。然后来到index.js中为它配一个路由,此时就不能单独给它配一个路由了,而是要配一个子路由:
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const routes = [
{
path: '/login',
component: Login
},
{
path: '/home',
component: () => import('../views/Home.vue'),
children: [
{
path: '/home/user',
component: () => import('../views/User.vue')
},
]
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
export default router;
在第二个对象里面放一个 children属性,也是一个数组,里面放上一个对象,为它配上路由。
配好了路由之后,我们就要将User组件加载Home组件里,就像当时Login组件要加载到App里一样。我们希望它展示在content容器里,于是我们这样写:
<div class="content">
<router-view></router-view>
</div>
当我们点击了用户管理后它就会被放到content容器中展示,也就是那块白色区域。
这样就实现了我们想要的效果。
还有个小细节要提,就是当用户在login页面登陆来到home页面时,默认就先要为用户展示用户管理页面吧,而不需要用户再去点击用户管理。你不能当用户来到home页面时为用户展示一片空白啊。
所以我们要在children中这样写:
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
const routes = [
{
path: '/login',
component: Login
},
{
path: '/home',
component: () => import('../views/Home.vue'),
children: [
{
path: '/home/user',
component: () => import('../views/User.vue')
},
{
path: '',
redirect: '/home/user'
},
]
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: routes
})
export default router;
redirect属性,当用户来到'/home'路径时,直接为用户展示'/home/user'。
我们来看一下效果:
这样就在home页面默认展示了用户管理页面,不需要用户再去点击了。
3. 总结
这样,我们大概学了一下Vue-Router的一些简单用法,我们来做个总结:
路由是指根据不同的URL请求,分配展示不同的 vue 组件的过程
router 只需要配置 path 和 component 的映射关系
router.push() 可以跳转到指定的路由
router.push({path:'/xxx',query:{xxx:xxx}}) 可以携带参数跳转
useRouter 可以获取路由的实例对象,它和router 文件下的 index.js中的路由对象是同一个
useRoute 可以获取当前路由的信息
- 二级路由的配置
将某个子路由配置在该路由的 children中,在该路由的组件中通过 router-view 渲染出来子路由的组件
这是一些基本的用法,能为页面配置路由,能实现页面的跳转,修改url地址。
如果对你有帮助的话不妨点个赞吧。