使用Vue Router创建一个路由守卫实例(内含代码链接)

420 阅读4分钟

知识介绍

什么是Vue Router?

Vue Router 是 Vue.js 官方的路由管理器,它深度集成了 Vue.js 的核心功能,使得开发者能够轻松地构建单页面应用(SPA)。Vue Router 提供了声明式的路由配置,允许你定义 URL 路径与要渲染的组件之间的映射关系,同时支持嵌套路由、动态路由参数、命名视图、导航守卫等功能。

什么是路由守卫?

路由守卫是 Vue Router 中用于控制导航的一种机制,它们是一系列的钩子函数,可以在路由转换的过程中被调用,从而实现对用户导航行为的控制。路由守卫可以用于:

  1. 验证用户权限:比如在用户访问需要登录才能看到的页面前检查用户是否已登录。
  2. 预加载数据:在显示新组件之前从服务器获取数据。
  3. 清理资源:在离开页面时清除不再需要的数据或资源,避免内存泄漏。
  4. 导航重定向:基于某些条件将用户重定向到另一个路由。

接下来,我们将通过一个路由实例,来学习路由守卫的应用。

正文

简单的登陆表单

  1. 显示一个登录页面,包含用户名和密码输入框以及登录按钮。
  2. 使用v-model指令绑定输入框的值到usernamepassword变量。
  3. 在表单提交时调用handleSubmit函数进行登录验证。
  4. handleSubmit函数中,如果用户名为admin且密码为123456,则将isLoggedIn设置到localStorage,并跳转到首页。
  5. 如果用户名或密码错误,则弹出警告框提示用户。
  6. 使用onMounted钩子函数检查localStorage中的isLoggedIn,如果已登录,则在500毫秒后跳转到首页。
<template>
    <div class="container mx-auto p-4">
        <h1 class="text-3xl font-bold mb-4">Login</h1>
        <form @submit.prevent="handleSubmit">
            <div class="mb-4">
                <label for="username" 
                class="block text-gray-700 text-sm font-bold mb-2">
                Username:
                </label>
                <input
                    required
                     type="text" id="username" v-model="username"
                     class="shadow appearance-none border rounded w-full
                     py-2 px-3 text-gray-700 leading-tight focus:outline-none
                     focus:shadow-outline"
                />
            </div>
            <div class="mb-6">
                <label for="password" 
                class="block text-gray-700 text-sm font-bold mb-2">
                Password:
                </label>
                <input
                    required
                     type="password" id="password" v-model="password"
                     class="shadow appearance-none border rounded w-full
                     py-2 px-3 text-gray-700 leading-tight focus:outline-none
                     focus:shadow-outline"
                />
            </div>
            <button 
                type="submit"
                class="bg-blue-500 hover:bg-blue-700 text-white font-bold
                    py-2 px-4 rounded focus:outline-none focus:shadow-outline"
            >Login</button>
        </form>
    </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'

const router = useRouter()
const username = ref('')
const password = ref('')

const handleSubmit = () => {
    if (username.value == 'admin' && password.value == '123456') {
        localStorage.setItem('isLoggedIn', 'true')
        router.push('/')
    } else {
        alert("用户名或密码错误")
    }
}

onMounted(() => {
    if (localStorage.getItem('isLoggedIn')) {
        console.log('不用重新登录');
        setTimeout(() => {
            router.push('/')
        }, 500)
    }
})
</script>

创建路由实例

  1. 首先,通过import语句引入createRoutercreateWebHashHistory方法。
  2. 然后,使用createRouter方法创建一个路由实例router,并传入一个配置对象。在配置对象中,设置了historycreateWebHashHistory(),表示使用哈希模式的路由历史记录。routes是一个数组,包含了各个路由规则的配置。
  3. routes数组中,每个元素都是一个路由规则的配置对象。其中,path表示路由的路径,name表示路由的名称,component表示该路由对应的组件。例如,第一个路由规则表示根路径/对应的组件是Home.vue
  4. 在第三个路由规则中,path/post/:id,其中id是一个动态参数,表示文章的ID。在路由匹配到该规则时,可以通过this.$route.params.id获取到具体的ID值。
  5. 在第四个路由规则中,meta属性表示该路由的元数据,其中requireAuth表示该路由需要用户认证才能访问。
  6. 最后,通过export defaultrouter实例导出,供其他模块使用。
  7. 在代码的最后,使用了router.beforeEach方法设置了一个全局的路由守卫。在每个路由切换之前,都会执行这个守卫函数。在守卫函数中,通过判断当前路由的meta.requireAuth属性,来决定是否需要用户认证。如果需要认证,就检查本地存储中的isLoggedIn值,如果已登录就继续前进,否则重定向到登录页面。如果不需要认证,就直接前进到下一个路由。
import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            path: '/',
            name: 'home',
            component: () => import('../views/Home.vue')
        },
        {
            path: '/post/:id',
            name: 'Detail',
            component: () => import('../views/Detail.vue')
        },
        {
            path: '/login',
            name: 'Login',
            component: () => import('../views/Login.vue')
        },
        {
            path: '/cart',
            name: 'Cart',
            meta: {
                requireAuth: true
            },
            component: () => import('../views/Cart.vue')
        }
    ]    
})
// 路由守卫
router.beforeEach((to, from, next) => {
    // console.log(to, from, '????????????');
    // next({path: '/login'})
    if (to.meta.requireAuth) {
        if (localStorage.getItem('isLoggedIn')) {
            next()
        } else {
            next({path: '/login'})
        }
    } else {
        next()
    }
})

export default router

实现效果

代码源

gitee.com/user8886/jj…

半成品项目,实现了路由守卫和部分其他功能。