Vue笔记7--路由管理Vue-router

1、Vue-router简介

路由核心:改变URL,但是页面不进行整体刷新。路由理解为指向的意思,其中有很重要的一个关键就是路由表。

路由表,是一个映射表,一个路由就是一组映射关系,key:value key用来表示路由,value可以是function或者是Component(组件)。

后端路由value为function用来处理客户端的请求,前端路由value为Component用来展示内容。

vue-router是基于路由和组件的,路由是用来设定访问路径,将路径和组件映射起来

npm install vue-router@4





2、项目结构

2.1 JavaScript

在src下创建router文件夹,新建index.js

从官网的router->基础->入门->JavaScript下复制1-4点

// 1. 定义路由组件.
// 也可以从其他文件导入
const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }

// 2. 定义一些路由
// 每个路由都需要映射到一个组件。
// 我们后面再讨论嵌套路由。
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

// 3. 创建路由实例并传递 `routes` 配置
// 你可以在这里输入更多的配置,但我们在这里
// 暂时保持简单
const router = VueRouter.createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
  history: VueRouter.createWebHashHistory(),
  routes, // `routes: routes` 的缩写
})

但还不能进行能够使用要稍加更改

在src下创建views文件,存放路由组件,新建Home.vueAbout.vue分别写上

<template>
    <div>home</div>
</template>
<template>
    <div>about</div>
</template>

index.js修改步骤1

// 1.从其他文件导入
import Home from '../views/Home.vue'
import About from '../views/About.vue'

步骤2中如果导入名字不同,需要修改component: Home

步骤3和4中可以不使用VueRouter.来获得createRouter。先在index最开始引入

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

然后去掉VueRouter.

const router = createRouter({
  history: createWebHashHistory(),
  routes, 
})

步骤4 有history模式也有hash模式,以后会讲解。

最后在结尾导出

export default router

在main.js中引入再使用

注意:这里是有先后顺序的app中用了路由,所以router要在前使用

//此处/index.js可省略会默认找到
import router from './router/index.js'

const app = createApp(App)
app.use(router)
app.mount('#app')



2.2 HTML

用自定义组件 router-link 代替a标签,最后渲染出来是a标签。达到可以在不重新加载页面的情况下更改 URL的目的,to填index.js步骤2中routes的path

<router-link to="/">Go to Home</router-link>

router-view

路由出口,占位符。路由匹配到的组件将渲染在这里

<router-view></router-view>





3、动态路由匹配

3.1 相应路由参数变化

比如在views下有一个User.vue组件,我希望不同的用户都能以这个组件为基础填上不同的信息。

App.vue

<router-link to="/use/123">Go to User</router-link>

此时我想要拿到数据123,需要

index.js

路径字段以冒号开始/user/:id,id的值将会在每个组件中以this.$router.params的形式暴露出params是参数的意思。但组合式API无法使用,因为setup中没有this。

注:动态路由无论id是什么都会进入user页面

const routes = [
    ...
    { path: '/user/:id', component: User },
]

Vue2做法

User.vue

<script>
export default{
    mounted(){
        console.log(this.$route.params.id)
    }
}
</script>

vue3做法

User.vue

vue-router引入useRoute()函数,再然后通过params访问id等参数。

<script setup>
import { useRoute } from 'vue-router';
    console.log(useRoute().params.id);
</script>



3.2 页面404

当输入不匹配的路由的时候我希望返回404页面

veiws文件夹下新建NotFound.vue。再在indes.js中引入,定义路由的时候使用正则的方式。

/:path(.*)表示匹配任意页面,但是如果前面出现了匹配成功的就不会走到正则这里。

const routes = [
    ...
    { path: '/:path(.*)', component: NotFound },
]



3.3 路由正则

?表示0个或1个 +号1个或多个 *号0个或多个

新建News.vue并且在index中导入

需求:动态路由的参数一定为数字。双杠表示匹配,d表示数字,+表示后面都为数字。[0-9]*也可。

const routes = [
    ...
    { path: "/news/:id(\\d+)", component:News}
]

需求:有多个参数也同样可以匹配,比如/news/123/aaa。+表示接受多个参数。

{
    path: "/news/:id+",
    component: News 
},

需求:参数可有可无,*和?表示参数可有可无。但是两者不同的点是问号不接受多个参数,比如/news/123/aaa

{ 
        //path: "/news/:id*",
        path: "/news/:id?",
        component: News 
},





4、嵌套路由

某些页面是多层组件嵌套的,子路由可以通过数据判断进哪一个。

在views中新建Parent.vue Styleone.vue Styleweo.vue

index.js

children:定义子路由,和routes一样以数组的形式定义,只是path前不需要加斜杠

const routes = [
    ...
    {
        path: '/parent',
        component: Parent,
        children: [
            { path: "styleone", component: StyleOne },
            { path: "styleone", component: StyleTwo },
        ]
    },
]

Parent.vue

<div>
    <h2>父组件Parent</h2>
    <RouterLink to="/parent/styleone">样式1</RouterLink>
    <RouterLink to="/parent/styletwo">样式2</RouterLink>
    <RouterView></RouterView>
</div>





5、编程式导航

5.1 JS转跳页面

除了RouterLink的转跳方法,比如登陆的时候我需要验证过后才允许转跳。

在 Vue 实例中,你可以通过 $router(一个对象) 访问路由实例。因而可以可以调用 this.$router.push、forword(返回)、go方法。

$route则是当前活跃的路由对象,在这里面就可以拿到path、params、query、name等。

在views中新建Page.vue

<button @click="goPage">跳转页面</button>
export default{
    methods:{
        goPage:function(){
            if (1 == 2)
                this.$router.push('/')
        }
    }
}

传入对象

this.$router.push({path:"/"})

带参数

this.$router.push({path:"/user/123456"})

或者利用name和params:分开写

index.js

const routes = [
    {name: "news",path: "/news/:id?",component: News},]

Page.vue

this.$router.push({ name: "news", params: { id: 123 } })

带问号

通过query:接受带问号的

this.$router.push({ path: "/about", query: { name: "zhangsan" } })

点击跳转网址显示为

http://localhost:5173/#/about?name=zhangsan

此时在About.vue中即可获取query里面内容,vue3中引入userRouter

export default{
    mounted(){
        console.log(this.$route.query.name)
    }
}



5.2 前进后退

替换当前位置

如果在一次访问ABC页面之后,B页面不想第二次展示,那么需要在历史纪录中,用C直接覆盖替换B。可在传递给 router.push中增加一个属性 replace: true

this.$router.push({ path: "/about", query: { name: "zhangsan" } ,replace:true})

或者用replace方法替换push

this.$router.replace({ path: "/about", query: { name: "zhangsan" } })

横跨历史

在历史堆栈中前进or后退多少步

About.vue

vue2写法

$router.go()方法参数正前进,负后退

 <button @click="goBack()">后退</button>
export default{
    methods:{
        goBack(){
            this.$router.go(-1)
        }
    }
}

vue3中引入userRouter后

router.go(-1)





6、命名路由和视图

6.1 命名路由

除了 path ,给路由起一个名字 name。下优点:

  • 没有硬编码的 URL
  • params 的自动编码/解码。
  • 防止你在 url 中出现打字错误。
  • 绕过路径排序(如显示一个)

App.vue

想要让to识别对象,绑定一下变成动态的

<router-link :to="{name:'news',params:{id:456}}">Go to News</router-link>



6.2 命名视图

在项目结构上components一般用于存放独立或者公共的组件,在views实际开发中通常会再根据页面新建文件夹,比如一个Home放着该页面下的组件

现在需求访问单个路径显示多个视图,同级展示。如访问/shop同时显示三个组件。(但似乎这种方式用的少)

新建ShopTop.vue ShopMain.vue ShopFooter.vue

index.js中引入

小名:组件。default:是必要的,提供默认显示。ShopTop:ShopTop可属缩写。

    {
        path:"/shop",
        components:{
            default:ShopMain,
            ShopTop,
            ShopFooter:ShopFooter,
        }
    },

App.vue

<router-view name="ShopTop"></router-view>
<router-view></router-view>
<router-view name="ShopFooter"></router-view>





7、重定向和别名

7.1 redirect:

当我希望访问//home链接都是home页面,可以在定义路由中使用redirect:

重定向

const routes = [
    {   path: '/',
        redirect:'/home'
    },
    { path: '/home', component: Home },
]

命名路由

除了路径还可已使用name

const routes = [
    {   path: '/',
        redirect: {name:"home"}
    },
    { path: '/home', name: "home", component: Home },
]

返回方法

这种做法可以在函数里写上判断,比如访问/:123参数to参会包含id=123的数据(但是不推荐),返回值可以是path也可以是name

const routes = [
    {   path: '/:id',
        redirect:(to)=>{
            console.log(to)
            return {path: '/home'}
        }
    },
]



7.2 alias:

起别名,数组形式可以

{path: '/parent',alias: '/father',...},
alias: ['/father', '/fuqin']





8、路由组件传参

使用$routeuseRoute()从URL上获得参数,会导致和路由紧密耦合,可以通过 props 配置来解除这种行为。

8.1 布尔模式

index.js

设置 props:true

const routes = [
    { 
        path: '/user/:id', 
        component: User,
        props:true,
    },
]

User.vue

vue2做法,此时this.id完美替代上面一句$route

<script>
export default {//路由组件传参vue2用法
    props: ['id'],
    mounted() {
        //console.log(this.$route.params.id);
        console.log(this.id);
    }
}
</script>

vue3做法,使用defineProps(),参数必为String类型

<script setup>
//import { useRoute } from 'vue-router';
//console.log(useRoute().params.id);
const props = defineProps({
    id: String
})
console.log(props.id)
</script>



8.2 命名视图

index.js

以数组的形式设置 props:

{
        path: "/shop/:id",
        components: {
            default: ShopMain,
            ShopTop,
            ShopFooter,
        },
        props:{default:true,ShopFooter:false,ShopTop:false}
    },

vue2做法,同布尔模式

vue3做法,同布尔模式

对象模式和函数模式具体见文档





9、历史记录模式

9.1 Hash模式

hash 模式是用 createWebHashHistory() 创建。标准是 URL 之前使用了一个哈希字符(#

http://localhost:8888/#/shop/123
const router = createRouter({
    history: createWebHashHistory(),
    routes, 
})
export default router



9.2 HTML5模式

createWebHistory() 创建 HTML5 模式,推荐使用这个模式,但是后端没配好就容易404

import {...,createWebHistory} from 'vue-router'
...
const router = createRouter({
    history:createWebHistory(),
    routes, 
})
export default router

即可访问

http://localhost:8888/home





10、路由进阶

10.1 导航守卫

通过跳转或取消的方式守卫导航。方式:全局的,单个路由独享的,或者组件级的。

全局前置守卫

用的较多,又称全全局守卫

使用 router.beforeEach 注册一个全局前置守卫,进入每一个路由组件的时候都会触发填入的回调函数。

回调函数参数1to去哪里,参数2from从哪来。

index.js

router.beforeEach((to, from) => {
    console.log(to)
    console.log(from)
})

参数3next导航守卫,当添加这个参数的时候,只有成功next()才会跳转。

router.beforeEach((to, from, next) => {
    console.log(to)
    console.log(from)
    next()//通行证
})

局部路由守卫

又称每路守卫,作用于单个路由,使用beforEnter:参数还是to、form、next

index.js

    {
        path: '/about',
        component: About,
        //每路守卫,独享的守卫
        beforeEnter: (to, from, next) => {
            console.log(to)
            console.log(from)
            if (1 == 1) {
                next()
            }
        }
    },

组件内的守卫

类似生命周期钩子,可以为路由组件添加以下配置:

  • beforeRouteEnter
  • beforeRouteUpdate
  • beforeRouteLeave

News.vue

<script>
export default {
    beforeRouteEnter() {
        console.log('路由进入组件之前');
    },
    beforeRouteUpdate() {
        console.log('路由更新组件之前');
    },
    beforeRouteLeave() {
        console.log('路由离开组件之前');
    },
}
</script>

同样也有参数to、form、next,因为beforeRouteEnter是还拿不到实例对象(另外两个可以),所以需要next写回调函数。

vm是自己取名的参数,相当于外面的this

export default {
    data() {
        return {
            age: 18,
        };
    },
    beforeRouteEnter(to, from, next) {
        next((vm)=>{
            console.log(vm.age)
        })
    },
}



10.2 路由懒加载

如果一次性要在index.js中引入非常多的组件,会导致加载很慢。

//静态导入
import Home from '../views/Home.vue'
...

路由懒加载,用到时候再加载

    {
        path: '/home',
        name: "home",
        component:()=>import('../views/Home.vue')
    },

但是更建议在抽取出来更好管理

const Home = () => import('../views/Home.vue')
const routes = [
    {
        path: '/home',
        name: "home",
        //component: Home
        component: Home
    },
]
posted @   北溟有咸其名为鸽  阅读(155)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示