Vue-Router:前端路由的无限可能

117 阅读5分钟

Vue - Router

认识路由

Vue路由是Vue.js框架中用于管理单页面应用程序(SPA)导航和页面之间切换的插件。它允许开发人员定义应用程序的不同路由,并且可以在用户与应用程序交互时动态地加载相应的组件。

Vue路由的主要特点包括:

  1. 路由映射:开发人员可以使用路由配置文件定义URL到组件的映射关系,使得当用户访问特定的URL时,相应的组件会被加载和渲染。
  2. 嵌套路由:Vue路由支持嵌套路由,允许在一个父级路由下定义子路由,从而构建复杂的页面结构。
  3. 路由参数:通过路由参数,开发人员可以在URL中传递参数,使得不同的URL可以渲染相同的组件,但根据参数的不同展示不同的内容。
  4. 导航守卫:Vue路由提供了导航守卫机制,允许开发人员在路由导航前后执行一些逻辑,比如进行权限验证、页面加载前的数据准备等。
  5. 动态路由:Vue路由支持动态路由,可以根据URL中的参数来动态加载不同的组件,实现页面的动态渲染。

Vue路由可以通过Vue Router插件来实现,它提供了一系列API和组件,使得开发人员可以轻松地构建复杂的单页面应用程序,并且实现良好的路由管理和用户体验。

  • 安装指令vue-router :npm i vue-router

路由模式

1. hash 模式
  • 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载,其显示的网路路径中会有 “#” 号,有一点点丑。比如 http://example.com/#/about。这是最安全的模式,因为他兼容所有的浏览器和服务器。

2. history 模式

依赖于 Html5 的 history,pushState API,所以要担心 IE9 以及一下的版本。并且还包括 back、forward、go 三个方法,对应浏览器的前进,后退,跳转操作。就是浏览器左上角的前进、后退等按钮进行的操作


3. abstract 模式(了解)

abstract 是 vue 路由中的第三种模式,本身是用来在不支持浏览器 API 的环境中,充当 fallback,而不论是 hash 还是 history 模式都会对浏览器上的 url 产生作用,本文要实现的功能就是在已存在的路由页面中内嵌其他的路由页面,而保持在浏览器当中依旧显示当前页面的路由 path,这就利用到了 abstract 这种与浏览器分离的路由模式


定义路由表

1. 在 src 下创建 router 目录, 并在目录里创建 index.js 文件
// 1. 引入第三方包的一些方法, 帮助我们创建路由
import { createRouter, createWebHashHistory } from 'vue-router'

const routes = [
    {
        // 路由地址
        path: "/",
        name: '/',
        // 对应路由显示组件
        component: () => import("../views/home.vue"),
    },
    {
        // 路由地址
        // path: "/login/:id/:name", //params传参
        path: "/login",
        name: 'login',
        // 对应路由显示组件
        component: () => import("@/views/login.vue"),
    },
    {
        // 路由地址
        path: "/cart",
        name: 'cart',
        // 对应路由显示组件
        component: () => import("../views/cart.vue"),
    },
    {
        path: '/banner',
        name: 'banner',
        // 对应路由显示组件
        component: () => import("../views/banner/index.vue"),
        children: [
            {
                path: 'bannerlist',
                name: 'bannerlist',
                // 对应路由显示组件
                component: () => import("../views/banner/components/bannerList.vue"),
            },
            {
                path: 'addbanner',
                name: 'addbanner',
                // 对应路由显示组件
                component: () => import("../views/banner/components/addBanner.vue"),
            },
        ]
    }
]

// 2. 创建一个路由实例
const router = createRouter({
    history:createWebHashHistory(),
    routes,
})

// 全局前置守卫
router.beforeEach((to, from) => {
    // 第一个形参:  要去到的页面对应的路由信息
    // 第二个形参: 从哪个页面去的对应的路由信息
    // console.log(to)
    // console.log(from)
    // console.log('全局路由守卫')
    console.log('全局路由守卫: beforeEach')
})
router.beforeResolve((to, from) => {
    console.log('全局路由守卫: beforeResolve')

})

// 3. 导出当前路由实例
export default router
导入挂载实例
import { createApp } from "vue";
import App from "./App.vue";
// 1. 导入路由实例
import router from './router'
const myApp = createApp(App);
// 2. 挂载路由实例
myApp.use(router)
myApp.mount("#app");

页面一级路由出口
<template>
    <h1>我是app 组件</h1>
    
    <!-- 路由出口, 符合条件的页面, 会在当前标签上展示 -->
    <router-view></router-view>
</template>

<script>
export default {
    data() {
        return {
        }
    },
};
</script>

<style>

</style>

跳转页面
<template>
    <h1>我是首页</h1>
    <button @click="btnclk">点击切换页面</button>
</template>
<script>
export default {
    methods: {
        btnclk() {
            // this.$router.replace('/cart')
            // this.$router.push('/login')
            // this.$router.push('/login/10008/nihao')

            // this.$router.push({
            //     name: 'login',
            //     params: {
            //         id: '10008',
            //         name: 'nihao'
            //     }
            // })


            // this.$router.push('/login?id=10000&name=nihao')


            this.$router.push({
                name: 'login',
                query: {
                    id: '10008',
                    name: 'nihao'
                }
            })

        }
    }
}
</script>
二级路由出口
<template>
    <h1>我是轮播图展示页面</h1>
    <router-link to="/banner/bannerlist">点击跳转list页面</router-link><br>
    <router-link to="/banner/addbanner">点击跳转添加页面</router-link><br>
    <!-- 二级路由出口 -->
    <router-view></router-view>
</template>

<template>
    <h1 style="color: blue;">我是轮播图展示列表页面</h1>
</template>

image.png

路由守卫

  • 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
  • 简单理解:导航守卫就是路由跳转过程中的一些钩子函数,再直白点路由跳转是一个大的过程,这个大的过程分为跳转前中后等等细小的过程,在每一个过程中都有一函数,这个函数能让你操作一些其他的事儿的时机,比如跳转前是否验证登录等,这就是导航守卫。

全局守卫

是指路由实例上直接操作的钩子函数,他的特点是所有路由配置的组件都会触发,直白点就是触发路由就会触发这些钩子函数。钩子函数按执行顺序包括 beforeEach、beforeResolve、afterEach 三个

beforeEach

在路由跳转前触发,参数包括 to,from,next(参数会单独介绍)三个,这个钩子作用主要是用于登录验证,也就是路由还没跳转提前告知,以免跳转了再通知就为时已晚

router.beforeEach((to, from, next) => {
    // to 将要访问的路径
    // from 代表从哪个路径跳转而来
    // next 是一个函数,表示放行 使用后 beforeEach 必须得调用next
    // next() 放行  next('/login') 强制跳转
});
beforeResolve
  • 这个钩子和 beforeEach 类似,也是路由跳转前触发,参数也是 to, from, next 三个,和 beforeEach 区别官方解释为:

    • 区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
    • 即在 beforeEach 和 组件内 beforeRouteEnter 之后,afterEach 之前调用
router.beforeResolve((to, from, next) => {
    // to 将要访问的路径
    // from 代表从哪个路径跳转而来
    // next 是一个函数,表示放行 使用后beforeEach 必须得调用next
    // next() 放行  next('/login') 强制跳转
});