VUE:详解路由(router)

VUE路由

ue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换

整体的实例

在这里插入图片描述
实例代码:

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
</head>

<body>
    <div id="app">
        <h1>Hello App!</h1>
        <p>
            <!-- 路由导航 router-link-->
            <router-link to="/foo" tag="button">Go to Foo</router-link>
            <router-link to="/bar" tag="button">Go to Bar</router-link>
        </p>
        <!-- 路由视图 router-view-->
        <router-view></router-view>
    </div>
    <script>
        //根据路由匹配规则创建一个路由器
        const router = new VueRouter({
            //定义路由匹配规则
            routes: [
                //其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。
                { path: '/foo', component: { template: '<div>foo</div>' } },
                { path: '/bar', component: { template: '<div>bar</div>' } }
            ]
        });
        //让这个实例使用此路由器
        new Vue({
            el: "#app",
            router: router,
        })
    </script>
</body>

</html>

效果图:
在这里插入图片描述

路由导航

①更换路由地址

<router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航,通过 to 属性指定目标地址
在这里插入图片描述
以下两种实现方式得到的效果一样
在这里插入图片描述

②tag属性

可以通过配置 tag 属性生成别的标签
在这里插入图片描述
效果图:
在这里插入图片描述

③自动设置类

当对应的路由匹配成功,将自动设置类
在这里插入图片描述
我们可以给这个类设置些默认的样式,达到让他实现选中的效果
在这里插入图片描述
效果图:
在这里插入图片描述
可以修改这两个默认的类名,用自己喜欢的类名来定义
在这里插入图片描述
效果图:
在这里插入图片描述
命名代码:

linkActiveClass: 'active',
linkExactActiveClass: 'active',

④设置行内样式

可以直接在router上设置行内样式或者class,是可以生效的,会自动注入到生成的网页标签上

<router-link style="color:red;font-size: 50px;" to="/foo">Go to Foo</router-link>

效果图:
在这里插入图片描述

路由视图

显示路由器中定义的组件

<!-- 路由视图 router-view-->
<router-view></router-view>

路由器

配置路由

首先要定义route, 一条路由的实现。它是一个对象,由两个部分组成: path和component. path 指路径,component 指的是组件

我们这里有两条路由,组成一个routes:

routes: [
	//其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。
	{ path: '/foo', component: { template: '<div>foo</div>' } },
	{ path: '/bar', component: { template: '<div>bar</div>' } }
]

创建router 对路由进行管理,它是由构造函数 new vueRouter() 创建,接受routes 参数

const router = new VueRouter({
      routes // routes: routes 的简写
})

配置完成后,把router 实例注入到 vue 根实例中,就可以使用路由了

new Vue({
	el: "#app",
	router: router,
})

完整代码:

<div id="app">
    <h1>Hello App!</h1>
    <p>
        <!-- 路由导航 router-link-->
        <router-link to="/foo" tag="button">Go to Foo</router-link>
        <router-link to="/bar" tag="button">Go to Bar</router-link>
    </p>
    <!-- 路由视图 router-view-->
    <router-view></router-view>
</div>
<script>
    //定义路由匹配规则
    var routes = [
        //其中"component" 可以是通过 Vue.extend() 创建的组件构造器,或者,只是一个组件配置对象。
        { path: '/foo', component: { template: '<div>foo</div>' } },
        { path: '/bar', component: { template: '<div>bar</div>' } }
    ]
    //根据路由匹配规则创建一个路由器
    const router = new VueRouter({
        routes
    });
    //让这个实例使用此路由器
    new Vue({
        el: "#app",
        router: router,
    });
</script>

单个路由"component" 的值可以只是一个组件配置对象也就是说可以通过 Vue.extend() 创建的组件构造器,如下:
在这里插入图片描述
效果图:
在这里插入图片描述

在组件中访问路由器对象

动态的路径参数(多种情况匹配同一个组件)

①基本使用

在这里插入图片描述
效果图:
在这里插入图片描述

②细节分析

  1. 前面路径相同然后冒号后面参数不一致,这些就会被同一个【动态路径参数】路由匹配到
  2. 匹配到的【路径参数】会变为$route.params的值,以一个对象中的键值对的形式存在
  3. 【动态路径参数】路由不管是在使用时还是在定义时都应该以冒号分隔路径与参数
  4. /user:666 只会匹配 /user:name这种形式的路由规则而不会匹配/user这个路由规则
  5. /user?name=dd&sex=dff, 只会匹配/user形式规则,而不会匹配/user:name这种形式的规则

③可设置多段【动态路径参数】

你可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中
在这里插入图片描述
效果图:
在这里插入图片描述

④可带查询参数

在这里插入图片描述
在这里插入图片描述

⑤动态路径的参数发生变化时,对应组件会被复用

当使用动态路径参数发生变化时,从例如/link:1导航到/link:2,原来的组件实例会被复用
因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

如下面的钩子函数只调用了一次,即复用了组件。如果是通过路由从其他组件过来的话,那么组件是会重新再次创建的
在这里插入图片描述
效果图:
在这里插入图片描述
可以看到mounted中的语句只执行了一次

⑥监听【动态的路径参数】的变化

路径参数变化时才会触发beforeRouteUpdate

在这里插入图片描述
在这里插入图片描述
如果你这时删除next方法的执行就可以阻止路由的跳转

⑦路由匹配的优先级

匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高

嵌套路由【显示多层级的路由视图】

①在组件中添加路由

在这里插入图片描述

②在路由器中添加子路由规则

在这里插入图片描述
效果图:
在这里插入图片描述

③在嵌套路由组件中影响跟路由与根视图

由于组件渲染的地方由对应路由的层级决定,所以只要我们在被嵌套的路由组件中的routr-link标签的to属性赋值为上层路由的路径,那么根视图就会渲染对应组件,从而实现常见业务:从子内容中跳转到主内容中去

//不管是决定路径还是相对路径都可以实现
<router-link to="/bar">foo_1</router-link>
<router-link to="../bar">foo_2</router-link>

编程式路由【通过JavaScript实现路由控制】

①概述

前面我们通过<router-link to=”” >这个路由标签来对路由进行导航,关于这个标签,实际上它是声明式路由的做法(通过标签直接声明)

我们还可以如同操作window.history一样进行编程式的操作路由(通过js编程)

②说明

Vue中的编程式路由是模仿window.history而实现的,所以其提供的api和window.history提供的api非常相似

③实现

实际上当你点击 时,router.push这个方法也会在内部调用,所以说,点击 <router-link :to="…"> 等同于调用 router.push(…)
在这里插入图片描述
这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL
效果图:
在这里插入图片描述

④注意

  1. 该方法的参数既可以是一个字符串路径,也可以是一个描述地址的对象
this.$router.push({path:"/foo"});
  1. 该方法的参数对象中还可以包含query查询对象
this.$router.push({ path: "/foo", query: { sex: "man", age: 18 } });
  1. 匹配动态路径参数
//等价于 /foo:123,会匹配规则为/foo:id的规则
this.$router.push({ path: "/foo:123"});

⑤router.replace

用户在提交一则信息,跳转到下一个页面后,如果点了返回按钮,用户就会返回到信息填写的页面,这对于像订单支付页面这种界面并不友好
这时我们就可以使用 replace方法替换掉push,replace方法会直接替换掉当前的 history 记录

methods: {
   toFoo:function(){
        this.$router.replace(
            {path:'/foo'},
        )
    }
}

如果使用router-link标签,直接在上面添加replace属性即可

<router-link :to="foo" replace>Go to foo</router-link>

⑥push/repalce 方法的回调函数

在 2.2.0+,可选的在 router.push 中提供 onComplete 和 onAbort 回调作为第二个和第三个参数
这些回调将会在导航成功完成 (在所有的异步钩子被解析之后) 或终止 (导航到相同的路由、或在当前导航完成之前导航到另一个不同的路由) 的时候进行相应的调用

对位传参

methods: {
   toFoo: function () {
        this.$router.replace({ path: "/foo"},
            function (to) {
                console.log("跳转成功", to);
            }, function (to) { //跳转失败时的目标路由 to 为undefined
                console.log("跳转失败", to);
            });
    }
}

注意:如果目的地和当前路由相同,只有参数发生了改变 (比如从一个用户资料到另一个 /users:1 -> /users:2),也会触发跳转成功的回调函数

⑦router.go(n)

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)

命名路由【通过名称找到真正路由】

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候,我们可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称

使用编程式路由:

//路由配置
const router = new VueRouter({
    routes: [
        {
            path: '/bar',
            component: Bar,
            name: "mybar",
        }
    ]

});
//调用
this.$router.push({ name: 'mybar' });

声明式路由

const router = new VueRouter({
    routes: [
        {
            path: '/bar',
            component: Bar,
            name: "mybar",
        }
    ]

});
//调用
<router-link :to="bar" tag="button" replace>路由导航2</router-link>
new Vue({
    el: "#app",
    router: router,
    data:{
        bar:{name:"mybar"}
    },
});

命名视图【为了同时显示多个视图】

当同级同时刻显示多个视图时,我们就可以使用命名视图了,我们可以在界面中拥有多个单独命名的视图,而不是只有一个单独的视图

如果 router-view 没有设置名字,那么默认为名字为 default

<div id="app">
    <h1>Hello App!</h1>
    <p>
        <router-link to="/foo" tag="button">路由导航1</router-link>
        <router-link to="/bar" tag="button">路由导航2</router-link>

    </p>
    <router-view style="border:1px solid black"></router-view>
    <router-view name="one" style="border:1px solid red"></router-view>
    <router-view name="two" style="border:1px solid green"></router-view>
</div>
<script>
    let Foo_1 = Vue.extend({
        template: `<div><h3>我是组件Foo1</h3></div>`,
    });
    let Foo_2 = Vue.extend({
        template: `<div><h3>我是组件Foo2</h3></div>`,
    });
    let Foo_3 = Vue.extend({
        template: `<div><h3>我是组件Foo3</h3></div>`,
    });
    let Bar_1 = Vue.extend({
        template: `<div><h3>我是组件Bar1</h3></div>`,
    });
    let Bar_2 = Vue.extend({
        template: `<div><h3>我是组件Bar2</h3></div>`,
    });
    let Bar_3 = Vue.extend({
        template: `<div><h3>我是组件Bar3</h3></div>`,
    });

    const router = new VueRouter({
        routes: [
            {
                path: '/foo', components: {
                    default: Foo_1,
                    one: Foo_2,
                    two: Foo_3,
                },
            },
            {
                path: '/bar', components: {
                    default: Bar_1,
                    one: Bar_2,
                    two: Bar_3,
                }
            },
        ]
    });
    new Vue({
        el: "#app",
        router: router,
    });
</script>

效果图
在这里插入图片描述

路由重定向

重定向方式一【根据路由路径重定向】

将路由规则中component选项修改为redirect,其值为一个路由的地址如:/foo

重定向结果:当跳转到路由为/test时会渲染/foo所在组件

<div id="app">
    <h1>Hello App!</h1>
    <p>
        <router-link to="/foo" tag="button">路由导航1</router-link>
        <router-link to="/bar" tag="button">路由导航2</router-link>
        <router-link to="/test" tag="button">重定向</router-link>

    </p>
    <router-view style="border:1px solid black"></router-view>
</div>
<script>
    let Foo = Vue.extend({
        template: `<div><h3>我是组件Foo</h3></div>`,
    });
    let Bar = Vue.extend({
        template: `<div><h3>我是组件Bar</h3></div>`,
    });
    const router = new VueRouter({
        routes: [
            { path: '/foo', component: Foo },
            { path: '/bar', component: Bar },
            { path: '/test', redirect: '/foo' }
        ]
    });
    new Vue({
        el: "#app",
        router: router,
    });
</script>

效果图:
在这里插入图片描述

重定向方式二【根据路由名称重定向】

在这里插入图片描述

重定向方式三【通过函数返回真正路由】

return 重定向的 字符串路径/路径对象
在这里插入图片描述

路由别名

/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样

<router-link to="/test" tag="button">路由导航2</router-link>
const router = new VueRouter({
    routes: [
        { path: '/bar', component: Bar, alias:'/test' },
    ]
});

在这里插入图片描述

路由组件传参

当我们通过路由规则跳转到不同的组件上时,我们可以在路由规则定义中传入参数

传参方式一:布尔模式

我们可以在路由规则对象上添加一个props属性,其值设置为true,如果 props 被设置为 true,route.params (动态路径参数,也就是冒号后面的东西) 将会被设置为组件属性
在这里插入图片描述
路由规则中冒号后面的路径参数会作为参数名,发起路由请求时传来的值就是其参数值。然后在组件中必须使用props来接收才能使用这个参数

效果图:
在这里插入图片描述
这里Foo组件规则中的props设置为false,所以接收不到参数

有多个路径参数
在这里插入图片描述
在这里插入图片描述

传参方式二:对象模式

在这里插入图片描述
效果图:
在这里插入图片描述

传参方式三:函数模式

可以创建一个函数返回 props。这样能够把静态值与基于路由的值结合作为参数传递给对应组件
在这里插入图片描述
效果图:
在这里插入图片描述

HTML5 History 模式

在这里插入图片描述
对前端而言,要将hash模式修改为history模式,只需要添加mode属性即可
在这里插入图片描述
友情提示:
对于history模式,需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器刷新时就会直接404了(使用history模式时不怕前进也不怕后退,就怕刷新…)所以呢,服务端需要增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面

导航钩子–beforeEach,afterEach,Next()

beforeEach

当我们通过路由来切换组件时,网页的标题不会改变

但其实我们是希望他改变的,或者有这种需求,这时候我们就可以使用路由钩子函数BeforeEach方法,他会在路由改变前触发
在这里插入图片描述

Next()

Next方法可以设置参数
当我们参数为false时,就可以取消导航
当我们设置为具体的路径时可以导航到指定页面
在这里插入图片描述

AfterEach

afterEach方法在路由改变后触发,一些较为实用的例子为:

  1. 当我们有一个较长的页面内容的组件,将他滚动到某个位置,在跳转到另一个组件。滚动条默认是在上一个组件停留的位置,而此时如果我们想回到顶端就可以通过after钩子实现。( window.scrollTo(0,0) )
  2. 从一个页面过渡到另一个页面,可以出现一个全局的加载动画,等到新页面加载完成在结束动画
    在这里插入图片描述
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值