Bootstrap

【Vue】路由

目录

单页面应用程序

概念

举例

单页面应用 VS 多页面应用

路由

什么是路由

vue3中的路由

在vue3中如何实现路由切换

vue文件的分类

存放目录

vue-router的基本使用

4个固定步骤

1、安装vue-router模块

2、导入相关函数,在main.js中编写代码

3、创建路由实例,还是在main.js中编写代码

4、注册路由实例

路由表规则编写

路由出口

抽离和封装路由模块

为什么要封装路由模块

如何封装路由模块

声明式导航(重要)

查询参传参

传递

接收

动态路由传参 

传递

接收

路由的其他配置

重定向 

404页面

路由的模式

编程式导航

编程式导航传参

路由嵌套

路由守卫


单页面应用程序

概念

整个应用只有一个入口网页文件(就是项目中index.html),换句话说,项目的所有功能都集中在同一个html中进行实现的,不会进行跳转。

举例

单页面应用程序:比如:网易云音乐、知乎等

多页面应用程序:比如:京东、淘宝、门户网站等

单页面应用 VS 多页面应用

开发分类实现方式页面性能开发效率用户体验学习成本首屏加载SEO
单页一个html按需更新,高不利于
多页多个html整页更新,低利于

什么是SEO

SEO称为搜索引擎优化,可以通过优化网站的内容和解构,提高网站在搜索引擎中的排名,从而增加网站的流量和曝光度的一种技术。

路由

什么是路由

路由是一种映射关系,比如生活中的路由:设备与ip地址的映射关系

vue3中的路由

路径与组件的映射关系,也就是,访问不同的路径,要显示不同的组件页面。

在vue3中如何实现路由切换

借助vue-router第三方模块,也是vue3的官方路由管理器

在进行路由切换前,我们需要先了解一下vue文件的分类和他们存放目录的问题,方便后期管理。

vue文件的分类

  1. 页面组件:一个做好的,大的,成型的页面,比如京东的首页,只是用来做大块的展示,无需复用,配合路由切换
  2. 复用组件:一个个独立的小型也米娜,可复用的,用来组装页面的

存放目录

  1. 页面组件:存放在src/views目录下
  2. 复用组件:存放在src/components目录下 

vue-router的基本使用

4个固定步骤

1、安装vue-router模块

npm i vue-router 

如果出现类似下面的错误,可以更换成 pnpm i vue-router 

npm error Cannot read properties of null (reading 'matches')
npm error A complete log of this run can be found in: C:\Users\L\AppData\Local\npm-cache\_logs\2024-12-03T02_31_00_941Z-debug-0.log 

2、导入相关函数,在main.js中编写代码

import { createRouter, createWebHashHistory } from 'vue-router'

3、创建路由实例,还是在main.js中编写代码

//创建路由实例
const router=createRouter({
    //指明路由模式,这里使用哈希模式,路径后面带#
    history:createWebHashHistory(),
    //路由表规则
    routes:[]
})

4、注册路由实例

//注册路由实例
app.use(router)

路由表规则编写

语法:

    routes:[

        {

            path:'自定义路径名',

            component:导入的页面组件名

        }

    ]

如下示例: 

//导入页面组件
import Find from './views/Find.vue'
import My from './views/My.vue'
//创建路由实例
const router=createRouter({
    //指明路由模式,这里使用哈希模式,路径后面带#
    history:createWebHashHistory(),
    //路由表规则
    routes:[
        {
            path:'/find',
            component:Find
        },
        {
            path:'/my',
            component:My
        }
    ]
})

路由出口

编写完路由表规则后,需要在App.vue写入路由出口,路由出口就是路由表内,页面组件的显示位置

 <router-view/>

抽离和封装路由模块

为什么要封装路由模块

        如果把路由配置的代码都写在main.js中,会使main.js代码显得臃肿。为了便于后期对路由代码的管理和维护,最好的方式就是把路由相关的代码单独封装到一个模块中,这是一种模块化开发的思想

如何封装路由模块

1、新建/src/router/index.js,然后把之前写在main.js中的路由代码全部移植到router/index.js中进行管理,并导出router实例,示例代码如下:

//导入相关函数
import { createRouter, createWebHashHistory } from 'vue-router'
//导入页面组件
import Find from '@/views/Find.vue'
import My from '@/views/My.vue'
//创建路由实例
const router=createRouter({
    //指明路由模式,这里使用哈希模式,路径后面带#
    history:createWebHashHistory(),
    //路由表规则
    routes:[
        {
            path:'/find',
            component:Find
        },
        {
            path:'/my',
            component:My
        }
    ]
})

//导出路由实例
export default router

注意:

这里在导入两个页面组件时,路径使用@,在 vite.config.js有定义,表示src绝对路径

2、在main.js中导入router实例,并注册,示例代码如下:

import './assets/main.css'

import { createApp } from 'vue'

import App from './App.vue'
//导入路由实例
import router from './router/index.js'
const app=createApp(App)
//注册路由实例
app.use(router)

app.mount('#app')


声明式导航(重要)

声明式导航就是点击链接跳转页面

实现方法

<router-link to="/path值"> 我的 </router>

PS:router-link的本质就是a标签 ,to属性会变成href属性。因此需要给router-link添加style就是给a标签添加style。

使用router-link跳转后,当前激活的导航链接中的a标签默认加了两个类名

router-link-exact-active 和 router-link-active

我们可以通过给这两个类添加高亮样式实现选中导航的样式。如下:

<template>
    <nav>
        <router-link to="/my">我的</router-link>
        <router-link to="/find">发现</router-link>
    </nav>
    <br/>
    <router-view/>
    
</template>

<script setup>
    import MyDialog from './components/MyDialog.vue';
</script>

<style scoped>
    nav a{
        color: #333;
        text-decoration: none;
        padding: 10px;
    }
    nav a.router-link-exact-active{
        background-color: aqua;
        color: blue;
    }
</style>

router-link-exact-active 和 router-link-active区别

  1. router-link-active:模糊匹配,当浏览器 # 后面放入url地址包含to属性值的时候,则会给当前的a标签添加此类名
  2. router-link-active:精准匹配,当浏览器 # 后面放入url地址等于to属性值的时候,则会给a标签添加此类名

相等是一种特殊的包含关系,因此只要当浏览器 # 后面放入url地址等于to属性值的时候,两个类名都会添加

查询参传参

传递

适用于传递多个参数

1、传字符串

<router-link to="/path?参数名="值"&参数名="值""></router-link>

2、传对象

<router-link :to="{path:'/path值',query:{参数值:值,参数值:值}}"></router-link>

接收

import  {useRoute} from 'vue-router'

//获取当前激活的路由对象

const route=useRoute()

const ret=route.query.参数名

动态路由传参 

路径比较简短些,需要改写路由规则表的path值

传递

1、传字符串

<router-link to="/path/10086"></router-link>

因为这种方式传递,会改变#后面的url,因此,我们需要先改写路由表的path值 

/friend/:fd  //:fd占位,fd这个名字自定义

2、传对象

需要给路由表中路由表项添加一个name属性

    routes:[

        {

            name:'Find',

            path:'/find/:fd',

            component:Find

        },

        {

            name:'My',

            path:'/my',

            component:My

        }

    ]

通过name、params传递

<router-link :to="{

        name:"Find",

        params:{

                fd:123
        }

}"></router-link>

接收

import  {useRoute} from 'vue-router'

//获取当前激活的路由对象

const route=useRoute()

const ret=route.params.参数名

路由的其他配置

重定向 

默认打开页面,会访问/根路径,这里借助redirect,让其强制跳转到其他页面 ,如下:

    routes:[

        {

            //配置这个路径,防止刚打开项目时,页面为空白

            path:'/',

            redirect:'/find'

        },

        {

            path:'/find',

            component:Find

        },

        {

            path:'/my',

            component:My

        }

    ]

404页面

需求:如果路由能命中,则显示响应的页面;否则,显示一个404页面

方法:在路由表末尾,添加一个404规则,当前面路由都没有命中,才会执行这条路由

{path:'./pathMatch(.*)*',component:_404}

路由的模式

默认采用的是哈希模式,特点是路径上会带上一个#,如果不想要这个#,可以更改路由模式,改成history模式。

import { createWebHistory } from 'vue-router'

const router=createRouter({

    //指明路由模式

    history:createWebHistory (),

})

注意:在Vite开发环境下,我们可以正常使用历史模式进行切换路由;但是当项目打包上线的时候,要想用历史模式,需要服务器支持和配置.

编程式导航

        前面的声明式导航是被动的跳转,在某些情况下,我们需要主动做路由跳转,比如:登录成功自动跳转至首页。

语法:

(1)获取router路由实例

import {useRouter} from 'vue-router'

const router=useRouter()  //router是路由实例,也是createRouter()返回值

这里要与之前const route = useRoute()做一个区分,route是当前激活的路由对象,用来获取路由参数的

(2)router.push(字符串/对象)

<script setup>
    import {useRouter} from 'vue-router'
    import {onMounted} from 'vue'
    const router = useRouter()

    onMounted(()=>{
        setTimeout(()=>{
            //字符串的方式,传入path对应的字符串
            router.push('/my')

            //对象的方式,传入一个包含path属性的对象
            router.push({path:'/my'})

            //对象的方式,传入一个包含name属性的对象
            router.push({name:'my'})
        },2000)
    })
</script>

编程式导航传参

编程式导航传参与声明式导航传参用法差不多

这里举例查询参传参

传字符串

router.push('/find?id=777')

传对象

router.push({

        path:'/find',

        query:{

                id:777

        }

路由嵌套

通过children添加子路由,编写规则与routes一致,包含path,component。子路由的path前面一般不添加 / ,记得编写完路由嵌套后,在需要添加子路由的页面组件中,添加路由出口和相应的router-link。

语法如下:

//路由表规则
    routes:[
        {
            path:'/',
            children:[
                {
                    path:'reconmand',
                    component:reconmand
                }
            ]

        },
        {
            path:'/find',
            component:Find
        },
    ]

示例如下:

路由配置:

import {createRouter,createWebHashHistory} from 'vue-router'

import Home from '@/views/Home.vue'
import Message from '@/views/Message.vue'
import My from '@/views/My.vue'
import Show from '@/views/Show.vue'
const router=createRouter({
  history:createWebHashHistory(),
  routes:[
    {
      path:'/home',
      component:Home,
      children:[
        {
          path:'message',
          component:Message
        },
        {
          path:'show',
          component:Show
        }
      ]
    },
    {
      path:'/message',
      component:Message
    },
    {
      path:'/my',
      component:My
    },
  ]
})
export default router

 App.vue,最上层的导航

<template>
  <nav>
    <router-link to="/home">Home</router-link>
    <router-link to="/my">About</router-link>
  </nav>
  <router-view></router-view>
</template>

<script setup>
    
</script>

<style scoped>

</style>

在Home页面添加子路由导航,也需要添加一个路由出口,代码如下:

<template>
<div>
    <nav>
        <router-link to="/home/message">Message</router-link>
        <router-link to="/home/show">Show</router-link>
    </nav>
    <router-view></router-view>
</div>
</template>

<script setup>
    
</script>

<style scoped>

</style>

路由守卫

路由守卫,全称叫做路由全局前置守卫,在访问每个页面前,添加权限判断

语法:

router.beforeEach((to,from)=>{

        //to:要去的路由对象

        //from:当前的路由对象

        //如果放行,返回true或undefined或者不写

        //如果不放行,返回false

        //重定向到某个指定路由,return 路径

})

示例:

const isLogin=false
//路由守卫
router.beforeEach((to,from,next)=>{
    if(to.path=='/my'&&!isLogin){
        alert('请先登录')
        return false
    }else{
        return true
    }
})

;