目录
一、Vue的路由
1、路由
路由:从源页面到目的页面的决策过程
2、前端路由
前端路由:在前端页面中维护的路由规则
(1)hash:在地址中以’#'分隔页面
(2)history:在地址中以’/'分隔页面
3、VueRouter路由
VueRouter路由 :路由就是根据一个请求路径选中一个组件进行渲染的决策过程。是Vue官方推出的路由管理器。
(1)route:表示单个路由。
(2)routes:表示多个路由的集合。是一个数组,在这个数组中包含了多个route
(3)router:译为路由器.是route、routes的管理者。当用户点击某个按钮或超链接时,路由的查找过程是
三者关系: router --> routes --> route
4、VueRouter的组成
(1)VueRouter类:维护的一种路由表,根据路由的请求去渲染某个组件
(2)router-link:类似于<a>标签。路由的链接组件
(3)router-view:路由出口,用于显示渲染的组件
5、VueRouter常用的函数:
(1)createRouter函数:创建路由器
(2)createWebHashHistory函数:创建Hash模式的路由
(3)createWebHistory函数:创建History模式路由
二、VueRouter的使用
1、安装vue-router
npm install vue-router
2、创建路由文件
(1)定义路由表:routes,在路由表中包含多个route
(2)创建路由器:router,在路由器中指定路由表(routes)以及路由模式(hash/history)
3、声明路由请求接口
声明路由请求接口:定义roter-link,'to’属性声明路由的目标路径
格式:<router-link to=“/about”>ABOUT</router-link>
4、声明路由出口
声明路由出口:指定组件渲染的位置
格式:<router-view></router-view>
☀️举个实例:
Home.vue组件代码段:
<template>
<h2>我是home组件</h2>
</template>
<script>
export default {
name: "Home"
}
</script>
About.vue组件代码段:
<template>
<h2>我是home组件</h2>
</template>
<script>
export default {
name: "Home"
}
</script>
routers目录下的router.js文件:
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import Home from "../components/Home.vue";
import About from "../components/About.vue";
const rs = [ //定义路由表
{
path:'/home',
component: Home,
name: 'home'
},
{
path:'/about',
component: About,
name: 'about'
}
]
//定义路由器
const router = createRouter({
routes:rs,
history: createWebHistory()
})
//导出路由器
export default router
main.js代码段:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './routers/router'
const app=createApp(App)
app.use(router)
app.mount('#app')
App.vue代码段:
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<!--创建路由的链接组件(路由接口)-->
<div>
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
<router-view></router-view>
</template>
三、动态路由
动态路由:是指路由器能够自动地建立自己的路由表,并且能够根据实际情况的变化适时地进行调整。
在路由中带有路由参数,路由参数会设置到’$route.params’中
1、动态路由的路径格式
动态路由的路径格式:/组件名/:参数名;在组件中通过’$route.params.参数名’获取参数。
☀️举例说明:
App.vue代码段:
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<!--创建路由的链接组件(路由接口)-->
<div>
<router-link to="/user/项羽">动态路由---项羽</router-link>
<router-link to="/user/刘邦">动态路由---刘邦</router-link>
</div>
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
<router-view></router-view>
</template>
User.vue组件代码段:
<template>
<h2>User组件</h2>
<p>欢迎回来,{{ $route.params.name }}</p>
</template>
<script>
export default {
name: "User"
}
</script>
routers目录下的router.js文件:
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import User from "../components/User.vue";
const rs = [ //定义路由表
{
path: '/user/:name',
component: User,
name:'user'
}
]
//定义路由器
const router = createRouter({
routes:rs,
history: createWebHistory()
})
//导出路由器
export default router
2、在URL中带查询参数
在URL中带查询参数:/组件名?参数名=参数值;在组件中通过’$route.query.参数名’获取参数
☀️举例说明:
App.vue代码段:
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<!--创建路由的链接组件(路由接口)-->
<div>
<router-link to="/library?id=1">图书1</router-link>
<router-link to="/library?id=2">图书2</router-link>
</div>
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
<router-view></router-view>
</template>
Library.vue组件代码段:
<template>
<h2>Library组件</h2>
<p>图书:{{ $route.query.id }}</p>
</template>
<script>
export default {
name: "Library"
}
</script>
routers目录下的router.js文件:
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
import Library from "../components/Library.vue";
const rs = [ //定义路由表
{
path: '/library',
component: Library,
name:'library'
}
]
//定义路由器
const router = createRouter({
routes:rs,
history: createWebHistory()
})
//导出路由器
export default router
3、通配符匹配
通配符匹配:'*'表示匹配所有路径。通常用于匹配前端的404页面
四、嵌套路由
嵌套路由:在组件中包含子组件的情况.vue官方提供children属性来定义这种嵌套关系。该属性是 一个数组,本质就是路由表
举一个实例:图书组件的嵌套
(1)图书列表组件:显示图书标题,每个标题都是链接组件,当用户点击链接组件(一级路由组件Books.vue)时,跳转到二级路由组件(Book.vue)
(2)图书组件:显示图书的详细信息
静态资源assets目录下的book.js文件:
export default[
{
id:1,
title:'Vue.js无难事',
desc:'前端框架经典图书'
},
{
id:2,
title:'React.js工程师宝典',
desc:'前端框架经典图书'
},
{
id:3,
title:'Go语言程序设计',
desc:'最流行的脚本语言'
}
]
Books.vue组件代码段:
<template>
<div>
<h2>图书列表</h2>
<ul>
<li v-for="book in bookList" :key="book.id">
<router-link :to="'/books/book/'+book.id">{{ book.title }}</router-link>
</li>
</ul>
</div>
<hr/>
<div>
<router-view></router-view>
</div>
</template>
<script>
import books from "../assets/books";
export default {
name: "Books",
data(){
return {
bookList:books
}
}
}
</script>
<style scoped>
li{
list-style-type: none;
margin-top: 25px;
}
</style>
Book.vue组件代码段:
<template>
<div>
<p>图书ID:{{book.id}}</p>
<p>图书名称:{{ book.title }}</p>
<p>描述:{{ book.desc }}</p>
</div>
</template>
<script>
import books from "../assets/books";
export default {
name: "Book",
data(){
return {
book: {}
}
},
created() {//获取第一次渲染时的数据,否则第一次渲染时$route对象得不到数据
this.book = books.find((item)=>item.id == this.$route.params.id)
},
watch : {
'$route':{ //监听路由参数的变化
handler:function (to){
this.book = books.find((item)=>item.id == this.$route.params.id)
}
}
}
}
</script>
routers目录下的router.js文件:
注意:component: ()=>import(‘…/components/Books.vue’)另一种引入组件的写法
import {createRouter, createWebHashHistory, createWebHistory} from "vue-router";
const rs = [ //定义路由表
{
path: '/books',
name: 'books',
component: ()=>import('../components/Books.vue'),
children: [{
path: '/books/book/:id',
component: ()=>import('../components/Book.vue')
}]
}
]
//定义路由器
const router = createRouter({
routes:rs,
history: createWebHistory()
})
//导出路由器
export default router
五、命名路由
命名路由:有时通过一个名称来标识路由会更方便,特别是在链接到路由,或者是执行导航时。可以创建Router实例时, 在routes选项中为路由设置名称
例如:将上例中的App.vue修改后同样可以的到相同的跳转效果:
App.vue代码段:
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<!--创建路由的链接组件(路由接口)-->
<div>
//<router-link to="/home">Home</router-link>
//
//<router-link to="/about">About</router-link>
<router-link :to="{name:'home'}">Home</router-link>
<router-link :to="{name:'about'}">About</router-link>
</div>
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
<router-view></router-view>
</template>
六、命名视图
命名视图:给路由视图()一个名称,可以将组件渲染到指定名称的路由视图中
1、给路由视图添加name属性。如:
上例的books.vue代码段修改如下:
<template>
<div>
<h2>图书列表</h2>
<ul>
<li v-for="book in bookList" :key="book.id">
<router-link :to="'/books/book/'+book.id">{{ book.title }}</router-link>
</li>
</ul>
</div>
<hr/>
<div>
<router-view name="test"></router-view>
</div>
<hr/>
<div>
<router-view name="bookDetail"></router-view>
</div>
</template>
<script>
import books from "../assets/books";
export default {
name: "Books",
data(){
return {
bookList:books
}
}
}
</script>
<style scoped>
li{
list-style-type: none;
margin-top: 25px;
}
</style>
2、在路由表中,指定components属性的值。如:
routers目录下的router.js文件:
{
path: '/books',
name: 'books',
component: ()=>import('../components/Books.vue'),
children: [{
path: '/books/book/:id',
//component: ()=>import('../components/Book.vue')
components:{
test:()=>import('../components/Book.vue')
}
}]
}
因为指定的路由视图是test,所以将会渲染到视图name为test上,也就是第一个 横线的下方,第二个横线的上方。(如果为bookDetail,则在第二条线的下方)
七、导航守卫
1、路由导航的方式:
(1)标签导航:<router-link to=“url”></router-link>
(2)编程式导航:this.$router.push(url)
2、导航守卫
导航守卫:在导航过程中由权限验证、数据的获取等业务的需要,会出现页面的重定向。
每个导航守卫都有三个参数(to,from,next)
- ‘to’:到哪里去
- ‘from’:从哪里来
- ‘next’:下一步去哪儿
(1)全局前置守卫:使用router.beforeEach注册,当一个导航触发时,前置守卫就会按路由规则进行匹配调用。保证next函数能够正常运行
☀️举个例子:
Login.vue代码段:
<template>
<div>
<h2>用户登录</h2>
<div>
<label>
UserName:
<input type="text" v-model.trim="username"/>
</label>
<br><br>
<label>
PassWord:
<input type="password" v-model.trim="password"/>
</label>
<br><br>
<button type="button" @click.prevent="login">登录</button>
</div>
<h3>{{ info }}</h3>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
username: '',
password: '',
info: ''
}
},
methods:{
login(){
if ("lisi"=== this.username && "12345"===this.password){ //合法用户,将用户信息写入页面缓存中
sessionStorage.setItem("isAuth",true);
this.info = "";
if (this.$route.query.redirect){ //合法用户请求页面参数存在,就进行页面跳转
let redirect = this.$route.query.redirect
this.$router.replace(redirect);
}else{
this.$router.replace('/home');
}
}else{
sessionStorage.setItem('isAuth',false)
this.username = ''
this.password = ''
this.info = '用户名或密码错误'
}
}
}
}
</script>
<style scoped>
</style>
Home.vue代码段:
<template>
<h2>我是首页</h2>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
main.js代码段(全局注册router):
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import router from './routers/index.js'
const app = createApp(App)
app.use(router)
app.mount('#app')
router文件下的路由index.js文件:
import { createRouter,createWebHistory } from 'vue-router';
import Home from '../components/Home.vue';
import Login from '../components/Login.vue';
const rs = [
{
path:'/home',
name:'home',
component:Home
},
{
path:'/login',
name:'login',
component:Login
}
]
const router = createRouter({
routes:rs,
history:createWebHistory()
})
//创建导航前置守卫
router.beforeEach((to,from,next)=>{
if(to.path == '/login'){ //若访问登录页面,则放行
next();
}else{
if(sessionStorage.getItem('isAuth')){//若用户已登录,则放行
next();
}else{
//用户没有登录,并且要访问受保护的资源,则将登录组件的地址告诉给next函数
next({
path:'/login',
query:{
redirect:to.fullPath
}
})
console.log(to.fullPath)
}
}
})
export default router;
App.vue代码段:
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
import Login from './components/Login.vue'
</script>
<template>
<img src="/vite.svg" class="logo" alt="Vite logo" />
<router-link :to="{name:'login'}" class="login">登录</router-link>
<router-view> </router-view>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
.login{
display: flex;
justify-content:center;
}
</style>