# 5. 路由-vue-router

https://router.vuejs.org/zh/api/

# 路由基本使用

<!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://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 引入Vue路由依赖js -->
    <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
</head>

<body>

    <div id="app">
        <!-- 路由跳转需要带上 # 号,因为 Vue-router 是基于哈希进行路由匹配的 -->
        <a href="#/login">login</a>
        <a href="#/register">register</a>
        <!-- 这是 vue-router 提供的元素,专门用来当做占位符。 -->
        <!-- 将来路由规则匹配到的组件就会展示到这个router-view中 -->
        <router-view></router-view>
    </div>

</body>
<script>

    // 组件的模板对象
    var login = {
        template: '<h1>登录组件</h1>'
    }
    var register = {
        template: '<h1>注册组件</h1>'
    }

    // 创建一个路由对象,当导入包后,在window全局对象中,就有了一个路由的构造函数,叫做VueRouter
    // 在new路由对象的时候,可以为构造函数,传递一个配置对象
    var router = new VueRouter({
        // 这个配置对象中的 route 表示【路由匹配规则】的意思。
        routes: [
            // 路由匹配规则
            // 每个路由规则,都是一个对象,这个规则对象身上有两个必须的属性:
            // 属性 1 是 path ,表示监听哪个路由链接地址;
            // 属性 2 是 component,表示如果路由是前面匹配到的 path ,则展示 component 属性对应的那个组件。
            // 注意:component 的属性值,必须是组件的对象,不能是组件名称。
            { path: '/login', component: login },
            { path: '/register', component: register }
        ]
    })


    // 
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router // 将路由规则对象,注册到Vue实例上,用来监听Url地址的变化,然后展示对应的组件。
    })

</script>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

# 路由跳转标签

router-link

Vue-router 官方提供了一个router-link元素标签。

它可以实现<a>标签的路由跳转,并且最终会渲染成为一个<a>标签,从而不需要在<a>标签中的href地址加#号进行跳转。

该元素有一个元素to属性,相当于<a>标签的href属性。

<router-link to='/login'>登录</router-link>
1

# 重定向方式

redirect

有一个需求,需要将项目根目录默认跳转到登录组件,可使用redirect重定向去登录的路由。

var router = new VueRouter({
        routes: [
            // 使用 redirect 重定向到登录路由。
            { path: '/', redirect: '/login' },
            { path: '/login', component: login },
            { path: '/register', component: register }
        ]
    })
1
2
3
4
5
6
7
8

# 修改router-link激活class默认值

配置当链接被精确匹配的时候应该激活的 class。注意默认值也是可以通过路由构造函数选项 linkExactActiveClass 进行全局配置的。

var router = new VueRouter({
    routes:[
        // 路由匹配...
    ],
    // 修改默认的激活 class 为 myActive
    linkExactActiveClass: 'myActive'
})
1
2
3
4
5
6
7

# 在路由中定义动画

<!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://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 引入Vue路由依赖js -->
    <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
    <style>
        .myActive {
            color: brown;
        }

        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(140px);
        }

        .v-enter-active,
        .v-leave-active {
            transition: all 0.5s ease;
        }
    </style>
</head>

<body>

    <div id="app">
        <router-link tag='span' to='/login'>登录</router-link>
        <router-link tag='span' to='/register'>注册</router-link>
        <!-- 直接使用 transition 包裹起来 -->
        <transition mode='out-in'>
            <router-view></router-view>
        </transition>
    </div>

</body>
<script>
    var login = {
        template: '<h1>登录组件</h1>'
    }
    var register = {
        template: '<h1>注册组件</h1>'
    }
    var router = new VueRouter({
        routes: [
            { path: '/login', component: login },
            { path: '/register', component: register }
        ],
        linkExactActiveClass: 'myActive'
    })


    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {}
    })

</script>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

# 在路由规则中定义参数

# 第一种方式

  1. router-link标签的to属性中添加 ?xx=xx 的形式把参数绑定在地址上。
  2. 通过this.$route.query来获取绑定在地址上的参数。
<router-link to='/login?id=12'>登录</router-link>

<script>
var login = {
    template: '#login',
    created() {
        console.info(this.$route.query.id)
    }
}
</script>

1
2
3
4
5
6
7
8
9
10
11

# 第二种方式

  1. 在规则中定义参数{ path:'/login:id',component: login }
var router = new VueRouter({
    routes: [
        { path: '/login/:id/:name', component: login }
    ]
})
1
2
3
4
5
  1. router-link标签的to属性中添加对应的参数
<router-link to='/login/12/张三'>登录</router-link>
1
  1. 通过this.$route.params来获取路由中的参数:
var login = Vue.extend({
    template: '<h1>登录组件 --- {{ this.$route.params.id }}</h1>'
})
1
2
3

# 使用children属性实现路由嵌套

路由嵌套简单来说就是父子路由,关键属性children

示例

<!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://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 引入Vue路由依赖js -->
    <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
    <style>
        .myActive {
            color: brown;
        }

        .v-enter,
        .v-leave-to {
            opacity: 0;
            transform: translateX(140px);
        }

        .v-enter-active,
        .v-leave-active {
            transition: all 0.5s ease;
        }
    </style>
</head>

<body>
    <div id="app">
        <router-link to='/account'>Account</router-link>
        <transition mode='out-in'>
            <router-view></router-view>
        </transition>
    </div>

    <template id='account'>
        <div>
            <h3>账号组件</h3>
            <!-- 如果在路由中,允许使用?xx=xx传参 -->
            <router-link to='/account/login'>登录</router-link>
            <router-link to='/account/register'>注册</router-link>

            <transition mode='out-in'>
                <router-view></router-view>
            </transition>
        </div>
    </template>

    <template id='login'>
        <div>
            <h3>登录组件</h3>
        </div>
    </template>

    <template id='register'>
        <div>
            <h3>注册组件</h3>
        </div>
    </template>

</body>
<script>

    var login = {
        template: '#login'
    }
    var register = {
        template: '#register'
    }
    var account = {
        template: '#account',
    }
    var router = new VueRouter({
        routes: [
            {
                path: '/account',
                component: account,
                // 使用 children 实现子路由的切换,注意 path 不要加`/`,否则永远以根路径匹配。
                // 下列所示 最终请求以 /account/login 访问。
                children: [
                    { path: 'login', component: login },
                    { path: 'register', component: register }
                ]
            }
        ],
        linkExactActiveClass: 'myActive'
    })

    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router
    })

</script>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

# 命名视图实现经典布局

在日常开发中,我们常见的项目采用的是经典的布局,有头部,左侧菜单,还有中间的主要内容。

使用VueRouter可以实现对组件命名,在router-view中指定name属性来进行组件的指定显示,从而实现一个页面多个组件显示。

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <!-- 开发环境版本,包含了有帮助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 引入Vue路由依赖js -->
    <script src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.js"></script>
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
        }

        .header {
            background-color: orange;
            height: 80px;
        }

        .container {
            display: flex;
            height: 600px;
        }

        h1 {
            margin: 0;
            padding: 0;
            font-size: 16px;
        }

        .left {
            background-color: lightgreen;
            flex: 2;
        }

        .main {
            background-color: pink;
            flex: 10;
        }
    </style>
</head>

<body>
    <div id="app">
        <router-view></router-view>
        <!-- 命名视图 -->
        <div class="container">
            <router-view name='left'></router-view>
            <router-view name='main'></router-view>
        </div>
    </div>
</body>
<script>

    var header = {
        template: '<h1 class="header">头部区域</h1>'
    }
    var menuBox = {
        template: '<h1 class="left">左部菜单区域</h1>'
    }
    var mainBox = {
        template: '<h1 class="main">主内容区域</h1>'
    }

    var router = new VueRouter({
        routes: [
            {
                path: '/', components: {
                    // default 相当于默认,即标签上没有name属性时默认显示该组件
                    'default': header,
                    'left': menuBox,
                    'main': mainBox
                }
            }
        ]
    })
    var vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        router
    })

</script>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
最近更新: 2019/10/17 上午4:20:42