vue3导航守卫讲解与使用
导航守卫是在 Vue Router 中提供的一种功能,它允许你在切换路由之前或之后执行一些逻辑。通过使用导航守卫,你可以控制用户是否可以访问路由、重定向、记录路由进入记录等。在 Vue Router 下,导航守卫包括全局守卫、路由独享守卫、组件内守卫,这些守卫可以用来完成不同层次的路由钩子函数。
今天借助讲解导航守卫的这篇文章讲解一个登录页面的案例,详细说明在日常开发过程中应该如何灵活的运用和操作这些函数,这里借助vue组件库 element-ui 进行润色,话不多说直接开整。
element-ui的安装与使用
找到element-ui官网:官方网址 ,然后终端执行如下命令安装第三方包:
# 选择一个你喜欢的包管理器
# NPM
$ npm install element-plus --save
# Yarn
$ yarn add element-plus
# pnpm
$ pnpm install element-plus
安装完成之后,在入口文件 mian.ts 进行插件的挂载:
import { createApp } from 'vue'
import App from './App.vue'
import {router} from "./router"
import ElementUi from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(router)
app.use(ElementUi)
app.mount('#app')
注意:如果您使用 Volar,请在 tsconfig.json 中通过 compilerOptions.type 指定全局组件类型。
// tsconfig.json
{
"compilerOptions": {
// ...
"types": ["element-plus/global"]
}
}
挂载完成之后,随便在官网上粘一段代码,如下查看效果是否被引入:
配置路由和设置路径别名
在router文件夹下的index.ts文件添加如下代码进行配置路由:
import { createRouter, createWebHistory } from 'vue-router'
export const router = createRouter({
history: createWebHistory(),
routes: [
{
path:'/',
component:()=>import('@/components/login.vue')
},
{
path:"/index",
component:()=>import("@/components/index.vue")
}
],
})
设置路径别名: 如果想在vite创建的vue3+ts项目中进行路径别名配置的话可以参考如下方式:
1)安装@types/node包提供了 Node.js 中核心模块的 TypeScript 类型声明:
npm install --save-dev @types/node
2)安装完成之后,进行 vite.config.ts 文件配置,如下 :
import { fileURLToPath,URL } from 'url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
resolve:{
alias:{
'@':fileURLToPath(new URL('./src',import.meta.url))
}
}
})
3)在tsconfig.json文件进行如下路径配置:
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
// ...
}
设置登录页面并实现规则跳转
制作登录界面:根据上文设置的element-ui组件库,接下来借助该组件库制作一个简易的登录界面,如下:
<template>
<div class="login">
<el-card class="box-card">
<el-form :model="formInline" class="demo-form-inline">
<el-form-item label="账号:">
<el-input v-model="formInline.user" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="密码:">
<el-input v-model="formInline.password" placeholder="请输入密码" type="password" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit" style="width: 100%">登录</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { useRouter } from 'vue-router';
type Form = {
user:string,
password:string
}
const router = useRouter()
const formInline = reactive<Form>({
user: '',
password: '',
})
const onSubmit = () => {
router.push('/index')
}
</script>
<style lang="less" scoped>
.login {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
</style>
输入框验证:根据上文呈现的登录页面的效果,接下来给登录框添加规则校验,如下:
import type { FormRules } from 'element-plus'
// 给登录框设置规则校验
const rules = reactive<FormRules>({
user:[
{
required:true,
message:"请输入用户名",
type:"string",
trigger:"blur"
}
],
password:[
{
required:true,
message:"请输入密码",
type:"string",
trigger:"blur"
}
]
})
设置完校验代码之后,给form添加rule规则,并且给每一个要规则校验的item添加对应的prop:
设置导航前置守卫
beforeEach:是Vue Router中的导航守卫之一,它用于在路由切换之前执行一些逻辑操作,例如检查用户是否登录或者获取一些路由需要的数据。它可以被用于全局,也可以用于单个路由或者路由组件中。当导航被触发时,它会按照它们添加的顺序依次被调用。如果其中任何一个导航守卫返回 false 或者是一个 Promise 并且被 reject,则导航会被取消。
我们先通过ref获取登录框的相关属性值:
然后给按钮设置点击事件,判断用户有没有输入用户名和密码,输入了就在浏览器本地存储个token,如下:
const onSubmit = () => {
form.value?.validate((validate)=>{
if(validate){
router.push('/index')
localStorage.setItem('token','success')
}else{
ElMessage.error("请输入用户/密码")
}
})
}
接下来可以在入口文件 main.ts 处设置前置守卫的代码了,根据如下代码的效果就可以实现在未登录的情况下是不能直接访问我们后台 index 路径下的路由的,登录之后会存放一个token,有token之后就可以直接访问后台 index 页面的内容了。
// 设置白名单
const whiteList = ['/']
// 设置路由前置守卫
router.beforeEach((to,from,next)=>{
if(whiteList.includes(to.path) || localStorage.getItem("token")){
next()
}else{
next('/')
}
})
设置导航后置守卫
afterEach:是 Vue Router 提供的一个全局守卫,它会在用户完成导航后被触发,无论是通过用户操作还是通过编写代码实现的导航。与 beforeEach 不同,afterEach 主要用于处理用户的导航完成之后需要进行的操作,例如页面统计、数据收集、用户行为分析等。
afterEach函数接收两个参数:to 和 from,分别表示目标路由和来源路由。我们可以在这个函数内部完成一些异步操作,例如向服务器发送统计数据、记录用户行为等,并在完成后更新页面的相关状态。
这里可以设置一个网页的进度条,在网页内容最顶部设置一个进度条来显示页面的加载程度,这里我将进度条单独抽离出一个组件:
<template>
<div class="wraps">
<div ref="bar" class="bar"></div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
let speed = ref<number>(1)
let bar = ref<HTMLElement>()
let timer = ref<number>(0)
const startLoading = ()=> {
speed.value = 1
let dom = bar.value as HTMLElement
timer.value = window.requestAnimationFrame(function fn(){
if(speed.value < 90){
speed.value+=1
dom.style.width = speed.value + '%'
timer.value = window.requestAnimationFrame(fn)
}else{
speed.value = 1
window.cancelAnimationFrame(timer.value)
}
})
}
const endLoading = () => {
let dom = bar.value as HTMLElement
setTimeout(()=>{
window.requestAnimationFrame(()=>{
speed.value = 100
dom.style.width = speed.value + '%'
})
},1000)
}
defineExpose({
startLoading,
endLoading
})
</script>
<style lang="less" scoped>
.wraps{
position: fixed;
top: 0;
width: 100%;
height: 2px;
.bar{
height: inherit; // 继承父级高度
width: 0;
background: red;
}
}
</style>
接下来在入口文件 main.ts 处设置导航后置守卫的内容:
注意:createVNode 是 Vue3 中的一个函数,用于创建一个虚拟节点,也就是 VNode 对象。它的作用是将模板编译成 VNode 对象,这个对象包含了节点的类型、属性、事件、子节点等信息,便于虚拟 DOM 操作和渲染。而且,相比较于 Vue2,Vue3 中的 createVNode 更加灵活和高效,可以手动地创建任何类型的节点,包括元素节点、组件节点、文本节点等。
其他路由相关操作
路由元信息:路由元信息指的是在 Vue Router 中,可以在路由配置中添加一些自定义信息,这些信息可以在路由组件中使用。通常包含了一些与路由相关的数据,例如当前路由的标题、面包屑等等。路由元信息可以在全局路由守卫中进行访问、修改和添加,也可以在单个路由配置中进行访问、修改和添加。
import { createRouter, createWebHistory } from 'vue-router'
export const router = createRouter({
history: createWebHistory(),
routes: [
{
path:'/',
component:()=>import('@/components/login.vue'),
meta:{
title:"登录页面"
}
},
{
path:"/index",
component:()=>import("@/components/index.vue"),
meta:{
title:"首页!!!"
}
}
],
})
在入口文件 mian.ts 处的前置路由守卫进行标题设置:
最后浏览器的网页标题就会动态的随着路由路径的切换而变化。
路由过渡动效:在路由中我们可以设置动画过渡效果,这里可以借助第三方动画库 animate ,具体的动画库的详细操作,我在之前的文章已经讲解过了:Vue--》实现动画与过渡效果 ,这里就不再赘述,仅仅展示如何使用:
在根App.vue组件处设置插槽来进行属性的引入:
<template>
<router-view #default="{route,Component}">
<transition :enter-active-class="`animate__animated ${route.meta.transition}`">
<component :is="Component"></component>
</transition>
</router-view>
</template>
<script setup lang="ts">
import "animate.css"
</script>
具体效果如下:
scrollBehavior:是Vue Router提供的一个钩子函数,用于控制路由跳转时页面滚动的行为。该函数接收三个参数,分别是 to、from 和 savedPosition。其中to和from都是路由对象,savedPosition 是一个位置对象,记录了页面跳转前的滚动条位置。
scrollBehavior 函数需要返回一个位置对象,用于指定页面跳转后的滚动条位置。例如,可以使用以下代码实现页面跳转时滚动到页面顶部:
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
return { x: 0, y: 0 };
}
})
除了返回一个对象以外,还可以返回一个 Promise 对象,以支持异步操作。例如,可以使用以下代码实现页面跳转时滚动到具有指定 ID 的元素处:
const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
if (to.hash) {
return new Promise(resolve => {
setTimeout(() => {
resolve({ selector: to.hash });
}, 100);
});
} else {
return { x: 0, y: 0 };
}
}
})
具体实现效果如下:
版权归原作者 亦世凡华、 所有, 如有侵权,请联系我们删除。