zoukankan      html  css  js  c++  java
  • 第十四节: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>

    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. replace替换当前位置

    4. 页面的前进和后退

     

     

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    [HNOI2002]营业额统计
    HDU 1374
    HDU 3345
    HDU 2089
    Graham扫描法
    Codeforces 1144D Deduction Queries 并查集
    Codeforces 916E Jamie and Tree 线段树
    Codeforces 1167F Scalar Queries 树状数组
    Codeforces 1167E Range Deleting
    Codeforces 749E Inversions After Shuffle 树状数组 + 数学期望
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/15413601.html
Copyright © 2011-2022 走看看