Vue(路由机制)

本文详细介绍了Vue路由的各个方面,包括安装、使用、重定向、动态路由匹配、嵌套路由、编程式导航、路由模式及导航守卫。特别讨论了hash模式和history模式的区别,并提供了页面跳转的多种实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

安装

使用

重定向

path和redirect实现重定向

name(大名)和redirect实现重定向

动态路由匹配

想对路由参数的变化作出响应的话,可以使用监听器或路由守卫

嵌套路由

编程式导航

编程式导航,可以使用path-query传参、name-params传参和name-query传参

路由模式

hash模式

history模式

hash路由和history路由的区别:

导航守卫

全局守卫(全局前置守卫、全局后置守卫)

路由独享守卫

组件内的守卫

面试题:实现页面跳转的方式?


vue-router是vue的一个插件,用来提供路由功能。通过路由的改变可以动态加载组件,达到开发单页面程序的目的。

安装

方式一 :CDN引入

<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.0-beta.7/vue.cjs.js"></script>

<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/4.0.10/vue-router.cjs.js"></script>

方式二:本地引入(js包)

<!-- 使用路由,先引入vue,再引入vueRouter -->

<script src="./js/vue-2.6.12.js"></script>

<script src="./js/vue-router-3.4.3.js"></script>

方式三:cnpm下载

cnpm install vue-router

使用

1、先引入vue,再引入vueRouter---<script src=''>

2、定义一个路由对象数组,由route路由对象组成---[{},{},{}]

3、创建路由器对象router(声明路由器对象实例)---new VueRouter

4、注册路由器对象(将路由实例对象导入vue实例对象)---router

5、使用路由(实现路由切换)---<router-link to=''>

6、路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域)---<router-view>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 1、使用路由,先引入vue,再引入vueRouter -->
    <script src="./js/vue-2.6.12.js"></script>
    <script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
    <div id="app">
        <!-- 5、使用路由(实现路由切换) -->
        <div>
            <router-link to="/a">去A路由</router-link>
            <router-link to="/b">去B路由</router-link>
        </div>
        <div>
            <!-- 6、路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
            <router-view></router-view>
        </div>
    </div>
    <script>
        // 声明组件
        let myA={
            template:`
                <div>A组件</div>
            `
        };
        let myB={
            template:`
                <div>B组件</div>
            `
        };
        // 2、定义一个路由对象数组,由route路由对象组成
        let routes=[
            {
                path:'/',
            },
            {
                path:'/a',
                component:myA
            },{
                path:'/b',
                component:myB
            }
        ];
        // 3、创建路由器对象router(声明路由器对象实例)
        let router=new VueRouter({
            // 声明配置路由对象
            routes:routes
        });
        new Vue({
            el:'#app',
            // 4、注册路由对象(将路由实例对象导入vue实例对象)
            // router:router,
            router,
            // 局部注册组件
            components:{
                'my-a':myA,
                'my-b':myB
            },
            data:{
                
            },
            methods: {
                
            },
        })
    </script>
</body>
</html>

router-link的本质是a标签

重定向

path和redirect实现重定向

name(大名)和redirect实现重定向

alias重命名(小名)

let routes=[
            {
                // path和redirect实现重定向
                path:'/',
                redirect:'/a'
            },
            {
                path:'/a',
                // 重命名(小名)
                alias:'/aa',
                component:myA
            }
        ];
let routes=[
            {
                path:'/',
                // name(大名)和redirect实现重定向
                redirect:{name:'aRoute'}
            },
            {
                path:'/a',
                name:'aRoute',
                // 重命名(小名)
                alias:'/aa',
                component:myA
            }
        ];

动态路由匹配

需要把某种模式匹配到的所有路由,全部映射到同一个组件。

例如 : 有一个user组件,对于所有id不同的用户,都要使用这个组件来渲染,那么可以在vue-router的路由路径中使用动态路径参数来达到这个效果。

1、路由器对象中path可以携带参数---path:'/user/id/:id/username/:username'

2、组件中created()接收路由器对象传递的参数---this.id=this.$route.params.id;

        // 声明组件
        let myA={
            data(){
                return{
                    id:null,
                    username:'',
                }               
            },
            // 接收路由器对象传递的参数
            created() {
                // console.log(this.$route,'路由对象');
                this.id=this.$route.params.id;
                this.username=this.$route.params.username;
            },
            template:`
                <div>A组件--{{id}}--{{username}}</div>
            `
        };
        // 定义一个路由对象数组,由route路由对象组成
        let routes=[
            {
                path:'/user/id/:id/username/:username',
                component:myA
            }
        ];

想对路由参数的变化作出响应的话,可以使用监听器或路由守卫

监听器---$route(to,from){ }---$route.params.xx

路由守卫---beforeRouteUpdate(to,from,next){ }---to.params.xx

        // 声明组件
        let myA={
            data(){
                return{
                    id:null,
                    username:'',
                }               
            },
            // 监听路由的变化并渲染到页面
            // 法一:监听器
            watch:{
                $route(to,from){
                    // to是新路由,from是旧路由
                    console.log(to,from,'监听路由参数变化');
                    this.id=this.$route.params.id;
                    this.username=this.$route.params.username;
                }
            },
            // 法二:路由守卫
            beforeRouteUpdate(to,from,next){
                // console.log(to.params,'路由参数');
                this.id=to.params.id;
                this.username=to.params.username;
                // 继续向下执行
                next();
                // 阻断继续向下执行
                next(false);
            },
            template:`
                <div>A组件--{{id}}--{{username}}</div>
            `
        };
        // 1、定义一个路由对象数组,由route路由对象组成
        let routes=[
            {
                path:'/user/id/:id/username/:username',
                component:myA
            }
        ];

嵌套路由

1、在父亲路由对象中设置二级路由

2、在父组件中使用子路由

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 使用路由,先引入vue,再引入vueRouter -->
    <script src="./js/vue-2.6.12.js"></script>
    <script src="./js/vue-router-3.4.3.js"></script>
</head>

<body>
    <div id="app">
        <!-- 使用路由(实现路由切换) -->
        <div>
            <router-link to="/user">用户界面</router-link>
            <router-link to="/manager">管理员界面</router-link>
        </div>
        <div>
            <!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
            <router-view></router-view>
        </div>
    </div>
    <script>
        // 声明组件
        let myA = {
            template: `
                <div>用户</div>
            `
        };
        let myB = {
            template: `
            // 在父组件中使用子路由
            <div>
                <div>
                    <router-link to="/managerChild1">子组件1</router-link>
                    <router-link to="/managerChild2">子组件2</router-link>
                </div>
                <div>
                    <!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
                    <router-view></router-view>
                </div>
            </div>
            `
        };
        let child1 = {
            template: `
                <div>子组件1</div>
            `
        };
        let child2 = {
            template: `
                <div>子组件2</div>
            `
        };
        // 定义一个路由对象数组,由route路由对象组成
        let routes = [
            {
                path: '/user',
                component: myA
            },
            {
                path: '/manager',
                component: myB,
                // 重定向
                redirect:'/managerChild1',
                // 在父亲路由对象中设置二级路由
                children: [
                    {
                        path: '/managerChild1',
                        component: child1
                    }, {
                        path: '/managerChild2',
                        component: child2
                    }
                ]
            }
        ];
        // 创建路由器对象router(声明路由器对象实例)
        let router = new VueRouter({
            // 声明配置路由对象
            routes: routes
        });
        new Vue({
            el: '#app',
            // 注册路由对象(将路由实例对象导入vue实例对象)
            // router:router,
            router,
            // 局部注册组件
            components: {
                'my-a': myA,
                'my-b': myB
            },
            data: {

            },
            methods: {

            },
        })
    </script>
</body>
</html>

编程式导航

除了使用 <router-link>创建 a 标签来定义导航链接,还可以借助 router 的实例方法,通过编写代码来实现。this.$router.push()跳转到指定路由,会向history栈添加一个新的记录,当用户点击浏览器回退按钮的时候,可以回到跳转前的url。

1、点击按钮跳转到指令路由---<button @click="$router.push('/a')">

2、组件中created()接收路由器对象传递的参数---console.log(this.$route);

编程式导航,可以使用path-query传参、name-params传参和name-query传参

path-query传参 ---参数会被拼接在浏览器地址栏中,并且刷新页面后数据也不会丢失

name-params传参 ---一次性携带参数,页面刷新参数失效

name-query传参

1、点击按钮触发事件

2、书写事件方法传递参数(编程式导航)---this.$router.push({ })

3、组件中created()接收参数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 使用路由,先引入vue,再引入vueRouter -->
    <script src="./js/vue-2.6.12.js"></script>
    <script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
    <div id="app">
        <!-- 使用路由(实现路由切换) -->
        <div>
            <router-link to="/a">去A路由</router-link>
            <router-link to="/b">去B路由</router-link>
        </div>
        <div>
            <!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
            <router-view></router-view>
        </div>
        <!-- 编程式导航跳转 -->
        <button @click="$router.push('/a')">跳转去A路由</button>
        <button @click="$router.push('b')">跳转去B路由</button>
        <!-- 编程式导航跳转并传递参数 -->
        <button @click="toPathA">跳转去A路由并传递参数</button>
        <button @click="toPathB">跳转去B路由并传递参数</button>
    </div>
    <script>
        // 声明组件
        let myA={
            data(){
                return{
                    id:null,
                    username:''
                }
            },
            template:`
                <div>A组件--{{id}}--{{username}}</div>
            `,
            // 接收参数
            created() {
                console.log(this.$route);
                // path直接传参或query传参
                this.id=this.$route.query.id;
                this.username=this.$route.query.username;
                
            },
        };
        let myB={
            template:`
                <div>B组件</div>
            `,
            // 接收参数
            created(){
                console.log(this.$route,'打印路由器对象');
            }
        };
        // 定义一个路由对象数组,由route路由对象组成
        let routes=[
            {
                path:'/a',
                component:myA
            },{
                path:'/b',
                component:myB,
                // name配合query进行参数传递
                name:'bRoute'
            }
        ];
        // 创建路由器对象router(声明路由器对象实例)
        let router=new VueRouter({
            // 声明配置路由对象
            routes:routes,
        });
        new Vue({
            el:'#app',
            // 注册路由对象(将路由实例对象导入vue实例对象)
            // router:router,
            router,
            // 局部注册组件
            components:{
                'my-a':myA,
                'my-b':myB
            },
            data:{
                
            },
            methods: {
                // 跳转到A页面
                toPathA(){
                    // 编程式导航
                    this.$router.push({
                        // 传递参数
                        // 法一:直接拼接在地址栏上
                        // path:'/a?id=1&username="张三"',
                        // 法二:path-query
                        path:'/a',
                        query:{id:1,username:"李四"}
                        // path-params无效!
                        // params:{
                        //     id:1,
                        //     username:'王五'
                        // }

                    })
                },
                // 跳转到B页面
                toPathB(){
                    this.$router.push({
                        name:'bRoute',
                        // 法三:name-query进行参数传递
                        query:{id:1,username:'赵六'},
                        // 法四:name-params进行参数传递(一次性参数)
                        params:{gender:'男'}
                    })
                }
            },
        })
    </script>
</body>
</html>

路由模式

 vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。如果不想要很丑的 hash,可以用路由的history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。不过这种模式要玩好,还需要后台配置支持。

hash模式

hash模式的工作原理是hashchange事件,可以在window监听hash的变化。我们在url后面随便添加一个#xx触发这个事件。

 window.onhashchange = function(event){
         console.log(event);
         // 打印出一个HashChangeEvent事件对象,在该对象内有newURL和oldURL
         // location.hash中也有相关的信息
         // 假设hash值是个颜色值,通过location.hash来获取到对应的hash值,然后设置页面中的某个元素的背景颜色来改变页面
 }

history模式

把window.history对象打印出来可以看到里边提供的方法和记录长度

history对象内有back(),forword(),go()等方法(前进,后退,跳转操作)

history.go(-3);//后退3次
history.go(2);//前进2次
history.go(0);//刷新当前页面
history.back(); //后退
history.forward(); //前进

hash路由和history路由的区别:

1、hash路由在地址栏URL上有#,而history路由没有会好看一点

2、进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)。

3、hash路由支持低版本的浏览器,而history路由是HTML5新增的API。

4、hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。

5、history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会马上向后端发送请求。

        // 创建路由器对象router(声明路由器对象实例)
        let router=new VueRouter({
            // 声明配置路由对象
            routes:routes,
            // 切换路由模式
            mode:'hash'
            // mode:'history'
        });

导航守卫

路由的改变会触发导航守卫

全局守卫(全局前置守卫、全局后置守卫)

全局前置守卫---router.beforeEach((to, from, next) => { })

全局后置钩子---router.afterEach((to, from) => { })

to:  即将要进入的目标路有对象

from: 当前导航正要离开的路由

next: Function : 一定要调用该方法来resolve这个钩子。执行效果依赖 next 方法的调用参数

路由独享守卫

该守卫与全局前置守卫的方法参数是一样的,且一定要调用该方法来resolve这个钩子

beforeEnter(to, from, next) => { }

组件内的守卫

beforeRouteEnter(to,from,next){ }---// this--window

beforeRouteUpdate(to,from,next){ }---//this--组件实例

beforeRouteLeave(to,from,next){ }---//this--组件实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 使用路由,先引入vue,再引入vueRouter -->
    <script src="./js/vue-2.6.12.js"></script>
    <script src="./js/vue-router-3.4.3.js"></script>
</head>
<body>
    <div id="app">
        <!-- 使用路由(实现路由切换) -->
        <div>
            <router-link to="/a">去A路由</router-link>
            <router-link to="/b">去B路由</router-link>
        </div>
        <div>
            <!-- 路由组件显示的位置(路由出口,匹配路由组件,渲染到这个区域) -->
            <router-view></router-view>
        </div>
        
    </div>
    <script>
        // 声明组件
        let myA={
            data(){
                return{
                    id:null,
                    username:''
                }
            },
            template:`
                <div>A组件--{{id}}--{{username}}</div>
            `,
            // 组件内的守卫
            beforeRouteEnter (to, from, next) {
                console.log(this,'beforeRouteEnter');
                // this指向全局对象window
                next();
            },
            beforeRouteLeave (to, from, next) {
                console.log(this,'beforeRouteLeave');
                // this指向组件实例
            },
            beforeRouteUpdate(to, from, next) {
                console.log(this,'beforeRouteUpdate');
                // this指向组件实例
            }
            
        };
        let myB={
            template:`
                <div>B组件</div>
            `,
            
        };
        // 定义一个路由对象数组,由route路由对象组成
        let routes=[
            {
                path:'/a',
                component:myA,
                // 路由独享守卫
                // beforeEnter(to,from,next){
                //     console.log(to,from,'路由独享守卫');
                //     next();
                // }
            },{
                path:'/b',
                component:myB,
            }
        ];
        // 创建路由器对象router(声明路由器对象实例)
        let router=new VueRouter({
            // 声明配置路由对象
            routes:routes,
            // 切换路由模式
            mode:'hash'
            // mode:'history'
        });
        // 全局守卫
        // 全局前置守卫
        // router.beforeEach((to,from,next)=>{
        //     console.log(to,from,'全局前置守卫');
        //     next();
        // });
        // 全局后置守卫
        // router.afterEach((to,from,next)=>{
        //     console.log(to,from,'全局后置守卫');
        // });
        // to:即将要进入的路由对象
        // from:当前导航正要离开的路由对象
        // next:function一定要调用该方法来触发后置守卫,跳转路由对应的页面


        new Vue({
            el:'#app',
            // 3、注册路由对象(将路由实例对象导入vue实例对象)
            // router:router,
            router,
            // 局部注册组件
            components:{
                'my-a':myA,
                'my-b':myB
            },
            data:{
                
            },
            methods: {
                
            },
        })
    </script>
</body>
</html>

面试题:实现页面跳转的方式?

a标签

<router-link>

编程式导航

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值