第十四节:VueRouter4.x简介、基本用法、路由懒加载(打包分析)、动态路由、路由嵌套、相关Api

一. 简介和基本用法

1. 简介

 (官网地址:https://next.router.vuejs.org/zh/introduction.html)

 Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成,让用 Vue.js 构建单页应用变得轻而易举。功能包括:

  • 嵌套路由映射
  • 动态路由选择
  • 模块化、基于组件的路由配置
  • 路由参数、查询、通配符
  • 展示由 Vue.js 的过渡系统提供的过渡效果
  • 细致的导航控制
  • 自动激活 CSS 类的链接
  • HTML5 history 模式或 hash 模式
  • 可定制的滚动行为
  • URL 的正确编码

PS:本章节使用的VueRouter版本为4.0.12

2. 基本用法

(1). 通过VueCli创建项目,并且选择包含VueRouter,会自动导入并生成VueRouter的相关配置文件

 A. 核心配置文件:src/router/index.js  (默认生成的文件如下,后面自己改造)

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

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

export default router
View Code

 B. main.js中需要以类似插件的形式导入vuerouter

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

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

(2). 在Views文件夹里创建两个组件页面 Home.vue 和 About.vue ,代码如下

Home.vue

<template>
    <div>
        我是Home组件
    </div>
</template>

<script>
    import { ref } from 'vue';

    export default {
        setup() {

        }
    }
</script>

<style scoped>
</style>
View Code

About.vue 

<template>
    <div>
        我是About组件
    </div>
</template>

<script>
    import { ref } from 'vue';

    export default {
        setup() {

        }
    }
</script>

<style scoped>
</style>
View Code

(3). 配置路由映射

 A. Home组件配置成直接加载,About组件配置成懒加载,并且将About组件打包后生成的名字配置成 about 。

 B. 通过createRouter创建路由对象,并且传入routes和Hash模式 

 C. 配置路由默认路径/,自动跳转到Home组件

代码分享:

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
    // 默认路径自动跳转到Home组件
    {
        path: "/",
        redirect: "/home"
    },
    // 下面匹配规则
    {
        path: '/home',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
    }
]

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

export default router

(4). 配置主页面

 在App.vue页面,利用<router-view />进行路由占位显示,利用</router-link>进行路由跳转操作。 

PS:<router-view>的作用,用来占位显示 <router-link> 链接到的组件。

App.vue代码如下: 

<template>
    <div>
        <div class="nav">
            <router-link to="/home">Home</router-link> |
            <router-link to="/about">About</router-link>
        </div>
        <router-view />
    </div>
</template>

<script>
    import { ref } from 'vue';

    export default {
        setup() {

        }
    }
</script>

<style scoped>
    .nav{
        margin-bottom: 20px;
    }
</style>
View Code

(5). 运行效果 

补充几个知识点:

1. 路由地址的模式

 有 hash模式 和 history模式,通过下面代码控制: createWebHashHistory是hash模式,createwebHistory是history模式

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

 hash模式的地址形式:http://localhost:8080/#/home

 history模式的地址形式:http://localhost:8080/home

2. <router-link>内质组件的属性

 (1). to属性:是一个字符串,或者是一个对象

 (2). replace属性:设置 replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push();

 (3). active-class属性:设置激活a元素后应用的class,默认是router-link-active;

 (4). exact-active-class属性:链接精准激活时,应用于渲染的 <a> 的 class,默认是router-link-exact-active;

eg: 设置如下代码,选中后的标签效果:

<style scoped>
    .router-link-active{
        color: green;
        font-weight: bold;
    }
</style>

 

二. 路由懒加载/打包分析

1. 背景

 当打包构建应用时,JavaScript 包会变得非常大,影响页面加载:

 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效;

PS:默认运行【npm run build】打包,会生成两个js文件,app.xxxx.js  和 chunk-vendors.xxxx.js ,app.js存放的是自己写的代码,chunk-vendors.js存放的是第三方依赖的代码。 

2. 实操

 这里可以用webpack的分包知识,Vue Router默认就支持动态来导入组件,从而提高首屏的渲染效率;

 用法:component可以传入一个组件,也可以接收一个函数,该函数 需要放回一个Promise;而import函数就是返回一个Promise;同时可以指定打包后生成的名字

如下:把About组件通过懒加载的方式进行导入,并且指定打包后生成的名字为about

const routes = [
    // 空路径自动跳转到Home组件
    {
        path: "/",
        redirect: "/home"
    },
    // 下面匹配规则
    {
        path: '/home',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
    }
]

3. 打包分析

  通过【npm run build】进行打包,打包后的文件如下:

 

三. 路由嵌套

1. 何为路由嵌套?

 目前我们匹配的Home、About、User等都属于底层路由,我们在它们之间可以来回进行切换;但是呢,我们Home页面本身,也可能会在多个组件之间来回切换:

 比如Home中包括Shops、Monent、Message,它们可以在Home内部来回切换;

 这个时候我们就需要使用嵌套路由,在Home中也使用 router-view 来占位之后需要渲染的组件;

2. 实操

(1). 路由配置文件

  需要在home组件下增加children节点,在里面配置相应的子路由。

核心代码:

const routes = [
    // 空路径自动跳转到Home组件
    {
        path: "/",
        redirect: "/home"
    },
    // 下面匹配规则
    {
        path: '/home',
        name: 'Home',
        component: Home,
        children: [
            //默认显示
            {
                path: '',
                redirect: '/home/message'
            },
            {
                path: 'message',
                component: () => import('../views/HomeMessage.vue')
            },
            {
                path: 'monent',
                component: () => import('../views/HomeMonent.vue')
            },
            {
                path: 'shops',
                component: () => import('../views/HomeShops.vue')
            }
        ]
    },
    {
        path: '/about',
        name: 'About',
        component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
    },
    {
        path: '/user',
        name: 'User',
        component: () => import( /* webpackChunkName: "user" */ '../views/User.vue')
    }
]

(2). Home组件

  通过router-link进行子页面的跳转,通过router-view进行占位。

<template>
    <div>
        我是Home组件
        
        
        <div class="home">
            <router-link to="/home/message">消息</router-link>
            <router-link to="/home/monent">动态</router-link>
            <router-link to="/home/shops">商品</router-link>
        </div>

        <!-- 路由占位符 -->
        <router-view></router-view>
    </div>
</template>

<script>
    import { ref } from 'vue';

    export default {
        setup() {

        }
    }
</script>

<style scoped>
    .home {
        margin: 40px 0;
    }
    .router-link-active {
        color: green;
        font-weight: bold;
    }
</style>
View Code

(3). 最终效果

 相关地址:http://localhost:8080/home/message   http://localhost:8080/home/monent   http://localhost:8080/home/shops

四. 动态路由剖析

1. 路由的其它属性

 name属性:路由记录独一无二的名称;

 meta属性:自定义的数据

2. 动态匹配规则

 很多时候我们需要将给定匹配模式的路由映射到同一个组件:

 例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但是用户的ID是不同的;

 在Vue Router中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数

3. 获取动态路由的值

(1). 在template模板中

 直接通过:$route.params.xxx来获取

    <div>
        我是User组件
        <div>我是传递过来的id值:{{$route.params.id}}</div>
    </div>

(2). 在created之类的生命周期中

 通过 this.$route.params.xxx 获取值

created() {
            console.log(this.$route.params);
            console.log(`我是created声明周期中获取的值${this.$route.params.id}`)
        },

(3). 在setup()中

 在setup中,我们要使用 vue-router库给我们提供的一个hook useRoute(注意:不是useRouter);该Hook会返回一个Route对象,对象中保存着当前路由相关的值;

<script>
    import { useRoute } from 'vue-router';

    export default {
        setup() {
            const route = useRoute();
            console.log(`我是setup中获取的值${route.params.id}`)
        }
    }
</script>

PS:匹配多个参数

4. 配置NotFound页面 

(1). 作用

 对于那些没有匹配到的路由,我们通常会匹配到固定的某个页面,比如NotFound的错误页面中,这个时候我们可编写一个动态路由用于匹配所有的页面;

(2). 实操

A. 在所有路由规则的最后,配置如下代码

{
        // 表示上面所有路径都匹配不到
        path: "/:pathMatch(.*)",
        component: () => import("../views/NotFound.vue")
    }

B. 在NotFound页面通过 $route.params.pathMatch 获取到传入的参数

<template>
    <div>
        我是NotFound页面
        <div>{{$route.params.pathMatch}}</div>
    </div>
</template>

C. 输入地址:http://localhost:8080/user/134543/testkk/3545    ,如下:

PS:

 

 

五. 相关Api

1. 页面的跳转push

(1) methods中

 通过this.$router.push实现。 

methods: {
            jumpTo1() {
                this.$router.push('/about');
            }
        }

(2). setup中

 需要引入 userRouter (注:不是userRoute) 这个hooks来实现。

<script>
    import { useRouter } from 'vue-router';

    export default {
        setup() {
            var router = useRouter();
            const jumpTo2 = () => router.push('/user/10086');
            
            return{
                jumpTo2
            }
        }
    }
</script>

在user页面,通过route.params.id获取参数值,即为10086

export default {
        created() {
            console.log(this.$route.params);
            console.log(`我是created声明周期中获取的值${this.$route.params.id}`)
        },
        setup() {
            const route = useRoute();
            console.log(`我是setup中获取的值${route.params.id}`)
        }
    }

2. query的方式传参和接收

页面传值代码

    import { useRouter } from 'vue-router';
    export default {
        setup() {
            var router = useRouter();// 测试传参2(query的方式)
            const jumpTo3=() => {
                router.push({
                    path: '/home/test2',
                    query: { name: 'ypf', age: 18 }
                })
            };

            return {
                jumpTo3
            }
        }
    }

页面接收代码

<script>
    import { useRoute } from 'vue-router';

    export default {
        setup() {
            
            const route=useRoute();
            
            // 1. query类型的接收
            console.log(route.query)
            console.log(route.query.name,route.query.age)

        }
    }
</script>

3. params的方式传参和接收

跳转代码

var router = useRouter();
    // 测试传参3(params的方式, 必须使用name属性跳转,不能用path跳转)
        const jumpTo4 = () => {
            router.push({
                name: 'test3',
                params: { name: 'ypf', age: 20 }
            });
        };

接收代码

export default {
        setup() {            
            const route=useRoute();
            
            // 1. param类型的接收
            console.log(route.params)
            console.log(route.params.name,route.params.age)
        }
    }

4. replace替换当前位置

5. 页面的前进和后退

 

 

 

 

 

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 
posted @ 2021-10-16 10:53  Yaopengfei  阅读(1301)  评论(2编辑  收藏  举报