• 学习目标:
    • 路由的基本概念与原理
    • Vue-router的基本使用
    • 高级路由
      • Vue-router嵌套路由
      • Vue-router动态路由匹配(路由传参)
      • Vue-router命名路由
      • Vue-router编程式导航
    • 基于vue-router的案例

【基本概念与原理】(P100~103)

路由是一个比较广义和抽象的概念,路由的本质就是对应关系。在开发中,路由分为:

  • 后端路由
  • 前端路由

1. 后端路由

  • 概念:根据不同的用户 URL 请求,返回不同的内容
  • 本质:URL 请求地址与服务器资源之间的对应关系

2. SPA(Single Page Application)

  • 后端渲染(存在性能问题)
  • Ajax前端渲染(前端渲染提高性能,但是不支持浏览器的前进后退操作)
  • SPA(Single Page Application)单页面应用程序:整个网站只有一个页面,内
    容的变化通过Ajax局部更新实现、同时支持浏览器地址栏的前进和后退操作
  • SPA实现原理之一:基于URL地址的hash(hash的变化会导致浏览器记录访问历
    史的变化、但是hash的变化不会触发新的URL请求)
  • 在实现SPA过程中,最核心的技术点就是前端路由

3. 前端路由

  • 概念:根据不同的用户事件,显示不同的页面内容
  • 本质:用户事件与事件处理函数之间的对应关系

4. 实现简易前端路由

  • 基于URL中的hash实现(点击菜单的时候改变URL的hash,根据hash的变化控制组件的切换)
1
2
3
4
// 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称
window.onhashchange = function() {
// 通过 location.hash 获取到最新的 hash 值
}

模拟路由:

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
</head>
<body>
<!-- 被 vue 实例控制的 div 区域 -->
<div id="app">
<!-- 切换组件的超链接 -->
<a href="#/zhuye">主页</a>
<a href="#/keji">科技</a>
<a href="#/caijing">财经</a>
<a href="#/yule">娱乐</a>

<!-- 根据 :is 属性指定的组件名称,把对应的组件渲染到 component 标签所在的位置 -->
<!-- 可以把 component 标签当做是【组件的占位符】 -->
<component :is="comName"></component>
</div>

<script>
// #region 定义需要被切换的 4 个组件
// 主页组件
const zhuye = {
template: '<h1>主页信息</h1>'
}

// 科技组件
const keji = {
template: '<h1>科技信息</h1>'
}

// 财经组件
const caijing = {
template: '<h1>财经信息</h1>'
}

// 娱乐组件
const yule = {
template: '<h1>娱乐信息</h1>'
}
// #endregion

// #region vue 实例对象
const vm = new Vue({
el: '#app',
data: {
comName: 'zhuye'
},
// 注册私有组件
components: {
zhuye,
keji,
caijing,
yule
}
})
// #endregion

// 监听 window 的 onhashchange 事件,根据获取到的最新的 hash 值,切换要显示的组件的名称
window.onhashchange = function() {
// 通过 location.hash 获取到最新的 hash 值
console.log(location.hash);
switch(location.hash.slice(1)){
case '/zhuye':
vm.comName = 'zhuye'
break
case '/keji':
vm.comName = 'keji'
break
case '/caijing':
vm.comName = 'caijing'
break
case '/yule':
vm.comName = 'yule'
break
}
}
</script>
</body>
</html>

5. Vue Router

Vue Router( 官网:https://router.vuejs.org/zh/ )是 Vue.js 官方的路由管理器。
它和 Vue.js 的核心深度集成,可以非常方便的用于SPA应用程序的开发。

Vue Router 包含的功能有:

  • 支持HTML5 历史模式或 hash 模式
  • 支持嵌套路由
  • 支持路由参数
  • 支持编程式路由
  • 支持命名路由

【Vue-router基本使用】(P104~105)

  1. 引入相关的库文件
  2. 添加路由链接
  3. 添加路由填充位
  4. 定义路由组件
  5. 配置路由规则并创建路由实例(重要!)
  6. 把路由挂载到 Vue 根实例中

1. 引入相关的库文件

1
2
3
4
<!-- 导入 vue 文件,为全局 window 对象挂载 Vue 构造函数 --> 
<script src="./lib/vue_2.5.22.js"></script>
<!-- 导入 vue-router 文件,为全局 window 对象挂载 VueRouter 构造函数 -->
<script src="./lib/vue-router_3.0.2.js"></script>

2. 添加路由链接

1
2
3
4
5
<!-- router-link 是 vue 中提供的标签,默认会被渲染为 a 标签 -->
<!-- to 属性默认会被渲染为 href 属性 -->
<!-- to 属性的值默认会被渲染为 # 开头的 hash 地址 -->
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>

3. 添加路由填充位

1
2
3
<!-- 路由填充位(也叫做路由占位符) -->
<!-- 将来通过路由规则匹配到的组件,将会被渲染到 router-view 所在的位置 -->
<router-view></router-view>

4. 定义路由组件

1
2
3
4
5
6
var User = {
template: '<div>User</div>'
}
var Register = {
template: '<div>Register</div>'
}

5. 配置路由规则并创建路由实例

1
2
3
4
5
6
7
8
9
10
11
// 创建路由实例对象 
var router = new VueRouter({
// routes 是路由规则数组,是我们的所有路由规则
routes: [
// 每个路由规则都是一个配置对象,其中至少包含 path 和 component 两个属性:
// path 表示当前路由规则匹配的 hash 地址
// component 表示当前路由规则对应要展示的组件,只接收组件对象,不接收字符串
{path:'/user',component: User},
{path:'/register',component: Register}
]
})

6. 把路由挂载到 Vue 根实例中

1
2
3
4
5
new Vue({
el: '#app',
// 为了能够让路由规则生效,必须把路由对象挂载到 vue 实例对象上
router
});

完整路由使用案例

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
template: '<h1>User 组件</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/user', component: User },
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

路由重定向

路由重定向指的是:用户在访问地址 A 的时候,强制用户跳转到地址 C ,从而展示特定的组件页面;
通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:

1
2
3
4
5
6
7
8
var router = new VueRouter({
routes: [
// 其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址
{path:'/', redirect: '/user'},
{path:'/user',component: User},
{path:'/register',component: Register}
]
})

【Vue-router嵌套路由】(P106)

1. 嵌套路由功能分析

通过路由的结构嵌套,在页面上展示出复杂的组件结构关系。

  • 点击父级路由链接显示模板内容
  • 模板内容中又有子级路由链接
  • 点击子级路由链接显示子级模板内容

2. 父路由组件模板

  • 父级路由链接
  • 父组件路由填充位
1
2
3
4
5
6
7
8
<p>
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
</p>
<div>
<!-- 控制组件的显示位置 -->
<router-view></router-view>
</div>

3. 子级路由模板

  • 子级路由链接
  • 子级路由填充位
1
2
3
4
5
6
7
8
9
10
const Register = {
template: `<div>
<h1>Register 组件</h1>
<hr/>
<router-link to="/register/tab1">Tab1</router-link>
<router-link to="/register/tab2">Tab2</router-link>
<!-- 子路由填充位置 -->
<router-view/>
</div>`
}

4. 嵌套路由配置

  • 父级路由通过children属性配置子级路由
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const router = new VueRouter({
routes: [
{ path: '/user', component: User },
{
path: '/register',
component: Register,
// 通过 children 属性,为 /register 添加子路由规则
children: [
{ path: '/register/tab1', component: Tab1 },
{ path: '/register/tab2', component: Tab2 }
]
}
]
})

或者:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user'},
{ path: '/user', component: User },
// children 数组表示子路由规则
{ path: '/register', component: Register, children: [
{ path: '/register/tab1', component: Tab1 },
{ path: '/register/tab2', component: Tab2 }
] }
]
})

完整嵌套路由使用案例

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
template: '<h1>User 组件</h1>'
}

const Register = {
template: `<div>
<h1>Register 组件</h1>
<hr/>

<!-- 子路由链接 -->
<router-link to="/register/tab1">tab1</router-link>
<router-link to="/register/tab2">tab2</router-link>

<!-- 子路由的占位符 -->
<router-view />
<div>`
}

const Tab1 = {
template: '<h3>tab1 子组件</h3>'
}

const Tab2 = {
template: '<h3>tab2 子组件</h3>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user'},
{ path: '/user', component: User },
// children 数组表示子路由规则
{ path: '/register', component: Register, children: [
{ path: '/register/tab1', component: Tab1 },
{ path: '/register/tab2', component: Tab2 }
] }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

【Vue-router动态路由匹配】(P107)

1. 动态匹配路由的基本用法

  • 思考:

    1
    2
    3
    4
    <!-- 有如下 3 个路由链接 -->
    <router-link to="/user/1">User1</router-link>
    <router-link to="/user/2">User2</router-link>
    <router-link to="/user/3">User3</router-link>
    1
    2
    3
    4
    // 定义如下三个对应的路由规则,是否可行???
    { path: '/user/1', component: User }
    { path: '/user/2', component: User }
    { path: '/user/3', component: User }
  • 应用场景:通过动态路由参数的模式进行路由匹配

    1
    2
    3
    4
    5
    6
    var router = new VueRouter({
    routes: [
    // 动态路径参数 以冒号开头
    { path: '/user/:id', component: User }
    ]
    })
    1
    2
    3
    4
    const User = {
    // 路由组件中通过$route.params获取路由参数(动态匹配上id值)
    template: '<div>User {{ $route.params.id }}</div>'
    }

基本动态路由匹配案例1:

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
template: '<h1>User 组件 -- 用户id为: {{$route.params.id}}</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user'},
{ path: '/user/:id', component: User },
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

2. 路由组件传递参数

$route.params.id与对应路由形成高度耦合,不够灵活,所以可以使用props将组件和路由解耦

(1) props的值为布尔类型

1
2
3
4
5
6
7
8
9
10
11
12
const router = new VueRouter({
routes: [
// 如果 props 被设置为 true,route.params 将会被设置为组件属性
// props: true表示开启路由的传参
{ path: '/user/:id', component: User, props: true }
]
})
const User = {
// 定义参数id,定义完就能访问和使用
props: ['id'], // 使用 props 接收路由参数
template: '<div>用户ID:{{ id }}</div>' // 使用路由参数
}
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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
props: ['id'],
template: '<h1>User 组件 -- 用户id为: {{id}}</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user'},
{ path: '/user/:id', component: User, props: true },
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

(2) props的值为对象类型

1
2
3
4
5
6
7
8
9
10
11
const router = new VueRouter({
routes: [
// 如果 props 是一个对象,它会被按原样设置为组件属性
// 此时id属性就没用了
{ path: '/user/:id', component: User, props: { uname: 'lisi', age: 12 }}
]
})
const User = {
props: ['uname', 'age'],
template: '<div>用户信息:{{ uname + '---' + age}}</div>'
}
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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
props: ['id', 'uname', 'age'],
template: '<h1>User 组件 -- 用户id为: {{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user'},
{ path: '/user/:id', component: User, props: { uname: 'lisi', age: 20 } },
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

(3) props的值为函数类型

1
2
3
4
5
6
7
8
9
10
11
12
const router = new VueRouter({
routes: [
// 如果 props 是一个函数,则这个函数接收 route 对象为自己的形参
{ path: '/user/:id',
component: User,
props: route => ({ uname: 'zs', age: 20, id: route.params.id })}
]
})
const User = {
props: ['uname', 'age', 'id'],
template: '<div>用户信息:{{ uname + '---' + age + '---' + id}}</div>'
}
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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
props: ['id', 'uname', 'age'],
template: '<h1>User 组件 -- 用户id为: {{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user' },
{
path: '/user/:id',
component: User,
props: route => ({ uname: 'zs', age: 20, id: route.params.id })
},
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

【Vue-router命名路由】(P109)

命名路由的配置规则

为了更加方便的表示路由的路径,可以给路由规则起一个别名,即为“命名路由”。

1
2
3
4
5
6
7
8
9
const router = new VueRouter({
routes: [
{
name: 'user', //给路由规则起的别名,帮助我们实现路由跳转
path: '/user/:id',
component: User
}
]
})
1
2
3
4
5
6
<!-- 原来的写法 -->
<router-link to="/user/3">User3</router-link>

<!-- 动态绑定命名路由后的写法 -->
<router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
router.push({ name: 'user', params: { id: 123 }})

命名路由完整案例:

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
props: ['id', 'uname', 'age'],
template: '<h1>User 组件 -- 用户id为: {{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>'
}

const Register = {
template: '<h1>Register 组件</h1>'
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user' },
{
// 命名路由
name: 'user',
path: '/user/:id',
component: User,
props: route => ({ uname: 'zs', age: 20, id: route.params.id })
},
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

【Vue-router编程式导航】(P110)

1. 页面导航的两种方式

  • 声明式导航:通过点击链接实现导航的方式,叫做声明式导航
    例如:普通网页中的 <a></a> 链接 或 vue 中的 <router-link></router-link>

  • 编程式导航:通过调用JavaScript形式的API实现导航的方式,叫做编程式导航
    例如:普通网页中的 location.href

2. 编程式导航基本用法

常用的编程式导航 API 如下:

  • this.$router.push('hash地址'):跳转到指定路由页面
  • this.$router.go(n):后退
1
2
3
4
5
6
7
8
9
const User = {
template: '<div><button @click="goRegister">跳转到注册页面</button></div>',
methods: {
goRegister: function(){
// 用编程的方式控制路由跳转
this.$router.push('/register');
}
}
}

案例:

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
<!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>
<!-- 导入 vue 文件 -->
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 被 vm 实例所控制的区域 -->
<div id="app">
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link :to="{ name: 'user', params: {id: 3} }">User3</router-link>
<router-link to="/register">Register</router-link>

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

<script>
const User = {
props: ['id', 'uname', 'age'],
template: `<div>
<h1>User 组件 -- 用户id为: {{id}} -- 姓名为:{{uname}} -- 年龄为:{{age}}</h1>
<button @click="goRegister">跳转到注册页面</button>
</div>`,
methods: {
goRegister() {
this.$router.push('/register')
}
},
}

const Register = {
template: `<div>
<h1>Register 组件</h1>
<button @click="goBack">后退</button>
</div>`,
methods: {
goBack() {
this.$router.go(-1)
}
}
}

// 创建路由实例对象
const router = new VueRouter({
// 所有的路由规则
routes: [
{ path: '/', redirect: '/user' },
{
// 命名路由
name: 'user',
path: '/user/:id',
component: User,
props: route => ({ uname: 'zs', age: 20, id: route.params.id })
},
{ path: '/register', component: Register }
]
})

// 创建 vm 实例对象
const vm = new Vue({
// 指定控制的区域
el: '#app',
data: {},
// 挂载路由实例对象
// router: router
router
})
</script>
</body>
</html>

3. 编程式导航参数规则

router.push() 方法的参数规则

1
2
3
4
5
6
7
8
// 字符串(路径名称)
router.push('/home')
// 对象
router.push({ path: '/home' })
// 命名的路由(传递参数)
router.push({ name: '/user', params: { userId: 123 }})
// 带查询参数,变成 /register?uname=lisi
router.push({ path: '/register', query: { uname: 'lisi' }})

》基于vue-router的案例(P111~116)

  • 用到的路由技术要点:

    • 路由的基础用法
    • 嵌套路由
    • 路由重定向
    • 路由传参
    • 编程式导航
  • 根据项目的整体布局划分好组件结构,通过路由导航控制组件的显示:

    1. 抽离并渲染 App 根组件
    2. 将左侧菜单改造为路由链接
    3. 创建左侧菜单对应的右侧路由组件
    4. 在右侧主体区域添加路由占位符
    5. 添加子路由规则
    6. 通过路由重定向默认渲染用户组件
    7. 渲染用户列表数据
    8. 编程式导航跳转到用户详情页
    9. 实现后退功能

》案例实现完整过程

1. 抽离并渲染 App 根组件

  • 案例初始模板页面素材:
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>基于vue-router的案例</title>
<style type="text/css">
html,
body,
#app {
margin: 0;
padding: 0px;
height: 100%;
}
.header {
height: 50px;
background-color: #545c64;
line-height: 50px;
text-align: center;
font-size: 24px;
color: #fff;
}
.footer {
height: 40px;
line-height: 40px;
background-color: #888;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
}
.main {
display: flex;
position: absolute;
top: 50px;
bottom: 40px;
width: 100%;
}
.content {
flex: 1;
text-align: center;
height: 100%;
}
.left {
flex: 0 0 20%;
background-color: #545c64;
}
.left a {
color: white;
text-decoration: none;
}
.right {
margin: 5px;
}
.btns {
width: 100%;
height: 35px;
line-height: 35px;
background-color: #f5f5f5;
text-align: left;
padding-left: 10px;
box-sizing: border-box;
}
button {
height: 30px;
background-color: #ecf5ff;
border: 1px solid lightskyblue;
font-size: 12px;
padding: 0 20px;
}
.main-content {
margin-top: 10px;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
ul li {
height: 45px;
line-height: 45px;
background-color: #a0a0a0;
color: #fff;
cursor: pointer;
border-bottom: 1px solid #fff;
}

table {
width: 100%;
border-collapse: collapse;
}

td,
th {
border: 1px solid #eee;
line-height: 35px;
font-size: 12px;
}

th {
background-color: #ddd;
}
</style>
</head>
<body>
<div>
<!-- 头部区域 -->
<header class="header">传智后台管理系统</header>
<!-- 中间主体区域 -->
<div class="main">
<!-- 左侧菜单栏 -->
<div class="content left">
<ul>
<li>用户管理</li>
<li>权限管理</li>
<li>商品管理</li>
<li>订单管理</li>
<li>系统设置</li>
</ul>
</div>
<!-- 右侧内容区域 -->
<div class="content right"><div class="main-content">添加用户表单</div></div>
</div>
<!-- 尾部区域 -->
<footer class="footer">版权信息</footer>
</div>
</body>
</html>
  • 引入相关库文件
1
2
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
  • 创建 Vue 实例对象
1
2
<!-- 要被Vue实例所控制的区域 -->
<div id="app"></div>
1
2
3
const vm = new Vue({
el: '#app'
})
  • 抽离 App 根组件
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
// 定义APP根组件
const App = {
template: `
<div>
<!-- 头部区域 -->
<header class="header">传智后台管理系统</header>
<!-- 中间主体区域 -->
<div class="main">
<!-- 左侧菜单栏 -->
<div class="content left">
<ul>
<li>用户管理</li>
<li>权限管理</li>
<li>商品管理</li>
<li>订单管理</li>
<li>系统设置</li>
</ul>
</div>
<!-- 右侧内容区域 -->
<div class="content right"><div class="main-content">添加用户表单</div></div>
</div>
<!-- 尾部区域 -->
<footer class="footer">版权信息</footer>
</div>`
}
  • 创建路由实例对象,配置路由规则
1
2
3
4
5
6
7
// 创建路由对象
const router = new VueRouter({
// 路由规则数组
routes: [
{ path: '/', component: App}
]
})
  • 把路由挂载到 Vue 根实例中,使其生效
1
2
3
4
const vm = new Vue({
el: '#app',
router
})
  • 放置路由占位符,页面才会展示路由根组件
1
2
3
4
5
<!-- 要被Vue实例所控制的区域 -->
<div id="app">
<!-- 路由占位符 -->
<router-view></router-view>
</div>

2. 将左侧菜单改造为路由链接

  • 将左侧菜单改造为路由链接
    • 改造前:
      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
      // 定义APP根组件
      const App = {
      template: `
      <div>
      <!-- 头部区域 -->
      <header class="header">传智后台管理系统</header>
      <!-- 中间主体区域 -->
      <div class="main">
      <!-- 左侧菜单栏 -->
      <div class="content left">
      <ul>
      <li>用户管理</li>
      <li>权限管理</li>
      <li>商品管理</li>
      <li>订单管理</li>
      <li>系统设置</li>
      </ul>
      </div>
      <!-- 右侧内容区域 -->
      <div class="content right"><div class="main-content">添加用户表单</div></div>
      </div>
      <!-- 尾部区域 -->
      <footer class="footer">版权信息</footer>
      </div>`
      }
    • 改造后
      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
      // 定义APP根组件
      const App = {
      template: `
      <div>
      <!-- 头部区域 -->
      <header class="header">传智后台管理系统</header>
      <!-- 中间主体区域 -->
      <div class="main">
      <!-- 左侧菜单栏 -->
      <div class="content left">
      <ul>
      <li><router-link to="/users">用户管理</router-link></li>
      <li><router-link to="/right">权限管理</router-link></li>
      <li><router-link to="/goods">商品管理</router-link></li>
      <li><router-link to="/orders">订单管理</router-link></li>
      <li><router-link to="/settings">系统设置</router-link></li>
      </ul>
      </div>
      <!-- 右侧内容区域 -->
      <div class="content right"><div class="main-content">添加用户表单</div></div>
      </div>
      <!-- 尾部区域 -->
      <footer class="footer">版权信息</footer>
      </div>`
      }

3. 创建路由组件+右侧添加占位符

  • 创建左侧菜单对应的右侧路由组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 创建左侧菜单对应的右侧路由组件
    const Users = { template: `<div>
    <h3>用户管理区域</h3>
    </div>` }
    const Right = { template: `<div>
    <h3>权限管理区域</h3>
    </div>` }
    const Goods = { template: `<div>
    <h3>商品管理区域</h3>
    </div>` }
    const Orders = { template: `<div>
    <h3>订单管理区域</h3>
    </div>` }
    const Settings = { template: `<div>
    <h3>系统设置区域</h3>
    </div>` }
  • 并在右侧主体区域添加路由占位符(将文本替换为占位符)

    • 添加前
      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
      // 定义APP根组件
      const App = {
      template: `
      <div>
      <!-- 头部区域 -->
      <header class="header">传智后台管理系统</header>
      <!-- 中间主体区域 -->
      <div class="main">
      <!-- 左侧菜单栏 -->
      <div class="content left">
      <ul>
      <li><router-link to="/users">用户管理</router-link></li>
      <li><router-link to="/right">权限管理</router-link></li>
      <li><router-link to="/goods">商品管理</router-link></li>
      <li><router-link to="/orders">订单管理</router-link></li>
      <li><router-link to="/settings">系统设置</router-link></li>
      </ul>
      </div>
      <!-- 右侧内容区域 -->
      <div class="content right"><div class="main-content">添加用户表单</div></div>
      </div>
      <!-- 尾部区域 -->
      <footer class="footer">版权信息</footer>
      </div>`
      }
    • 添加后
      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
      // 定义APP根组件
      const App = {
      template: `
      <div>
      <!-- 头部区域 -->
      <header class="header">传智后台管理系统</header>
      <!-- 中间主体区域 -->
      <div class="main">
      <!-- 左侧菜单栏 -->
      <div class="content left">
      <ul>
      <li><router-link to="/users">用户管理</router-link></li>
      <li><router-link to="/right">权限管理</router-link></li>
      <li><router-link to="/goods">商品管理</router-link></li>
      <li><router-link to="/orders">订单管理</router-link></li>
      <li><router-link to="/settings">系统设置</router-link></li>
      </ul>
      </div>
      <!-- 右侧内容区域 -->
      <div class="content right"><div class="main-content">
      <router-view />
      </div></div>
      </div>
      <!-- 尾部区域 -->
      <footer class="footer">版权信息</footer>
      </div>`
      }

4. 添加子路由规则+路由重定向

  • 添加子路由规则

    • 添加前
      1
      2
      3
      4
      5
      6
      7
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      { path: '/', component: App}
      ]
      })
    • 添加后
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      {
      path: '/',
      component: App,
      children: [
      { path: '/users', component: Users },
      { path: '/rights', component: Rights },
      { path: '/goods', component: Goods },
      { path: '/orders', component: Orders },
      { path: '/settings', component: Settings }
      ]
      }
      ]
      })
  • 通过路由重定向默认渲染用户组件:redirect: '/users',

    • 对根组件进行路由重定向使其默认访问/users子路由(因为根组件是空白的)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      {
      path: '/',
      component: App,
      redirect: '/users',
      children: [
      { path: '/users', component: Users },
      { path: '/rights', component: Rights },
      { path: '/goods', component: Goods },
      { path: '/orders', component: Orders },
      { path: '/settings', component: Settings }
      ]
      }
      ]
      })

5. 渲染用户列表数据

  • 找到用户列表组件,定义date私有数据

    • 插入数据前
      1
      2
      3
      4
      // 创建左侧菜单对应的右侧路由组件
      const Users = { template: `<div>
      <h3>用户管理区域</h3>
      </div>` }
    • 插入数据后
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      // 创建左侧菜单对应的右侧路由组件
      const Users = {
      data() {
      // 返回一个数据对象,返回的数据对象是用户列表的数组
      return {
      userlist: [
      { id: 1, name: '张三', age: 17 },
      { id: 2, name: '李四', age: 18 },
      { id: 3, name: '王五', age: 19 },
      { id: 4, name: '赵六', age: 20 }
      ]
      }
      },
      template: `<div>
      <h3>用户管理区域</h3>
      </div>`
      }
  • 修改页面模板,并循环渲染出数据

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
// 创建左侧菜单对应的右侧路由组件
const Users = {
data() {
// 返回一个数据对象,返回的数据对象是用户列表的数组
return {
userlist: [
{ id: 1, name: '张三', age: 17 },
{ id: 2, name: '李四', age: 18 },
{ id: 3, name: '王五', age: 19 },
{ id: 4, name: '赵六', age: 20 }
]
}
},
template: `<div>
<h3>用户管理区域</h3>
<table>
<thead>
<tr><th>编号</th><th>姓名</th><th>年龄</th><th>操作</th></tr>
</thead>
<tbody>
<tr v-for="item in userlist" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td><a href="javascript:;">详情</a></td>
</tr>
</tbody>
</table>
</div>`
}

6. 编程式导航跳转+实现后退功能

  • 编程式导航跳转到用户详情页(跳转的时候实现路由传参,把用户id传过去)

    • 定义用户详情页的组件
      1
      2
      3
      4
      5
      const UserInfo = {
      template: `<div>
      <h5>用户详情页</h5>
      </div>`
      }
    • 添加路由规则(用户详情页的路由级别和用户管理区域应该是平级的),添加后:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      {
      path: '/',
      component: App,
      redirect: '/users',
      children: [
      { path: '/users', component: Users },
      { path: '/userInfo', component: UserInfo },
      { path: '/rights', component: Rights },
      { path: '/goods', component: Goods },
      { path: '/orders', component: Orders },
      { path: '/settings', component: Settings }
      ]
      }
      ]
      })
    • 此时依旧是无法跳转的,还需为超链接绑定点击事件,并定义相应的事件处理函数
      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
      // 创建左侧菜单对应的右侧路由组件
      const Users = {
      data() {
      // 返回一个数据对象,返回的数据对象是用户列表的数组
      return {
      userlist: [
      { id: 1, name: '张三', age: 17 },
      { id: 2, name: '李四', age: 18 },
      { id: 3, name: '王五', age: 19 },
      { id: 4, name: '赵六', age: 20 }
      ]
      }
      },
      methods: {
      goDetail(id) {
      // 查看是否拿到参数:
      // console.log(id)
      // 通过编程式导航实现页面跳转:
      this.$router.push('/userInfo')
      }
      },
      template: `<div>
      <h3>用户管理区域</h3>
      <table>
      <thead>
      <tr><th>编号</th><th>姓名</th><th>年龄</th><th>操作</th></tr>
      </thead>
      <tbody>
      <tr v-for="item in userlist" :key="item.id">
      <td>{{item.id}}</td>
      <td>{{item.name}}</td>
      <td>{{item.age}}</td>
      <td><a href="javascript:;" @click="goDetail(item.id)">详情</a></td>
      </tr>
      </tbody>
      </table>
      </div>`
      }
    • 此时可以实现跳转了,但浏览器地址栏没有参数,现在让它跳转的同时把id当参数传过来
      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
      // 创建左侧菜单对应的右侧路由组件
      const Users = {
      data() {
      // 返回一个数据对象,返回的数据对象是用户列表的数组
      return {
      userlist: [
      { id: 1, name: '张三', age: 17 },
      { id: 2, name: '李四', age: 18 },
      { id: 3, name: '王五', age: 19 },
      { id: 4, name: '赵六', age: 20 }
      ]
      }
      },
      methods: {
      goDetail(id) {
      // 查看是否拿到参数:
      // console.log(id)
      // 通过编程式导航实现页面跳转:
      this.$router.push('/userInfo/' + id)
      }
      },
      template: `<div>
      <h3>用户管理区域</h3>
      <table>
      <thead>
      <tr><th>编号</th><th>姓名</th><th>年龄</th><th>操作</th></tr>
      </thead>
      <tbody>
      <tr v-for="item in userlist" :key="item.id">
      <td>{{item.id}}</td>
      <td>{{item.name}}</td>
      <td>{{item.age}}</td>
      <td><a href="javascript:;" @click="goDetail(item.id)">详情</a></td>
      </tr>
      </tbody>
      </table>
      </div>`
      }
      路由规则也要标记为动态参数
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      {
      path: '/',
      component: App,
      redirect: '/users',
      children: [
      { path: '/users', component: Users },
      { path: '/userInfo/:id', component: UserInfo },
      { path: '/rights', component: Rights },
      { path: '/goods', component: Goods },
      { path: '/orders', component: Orders },
      { path: '/settings', component: Settings }
      ]
      }
      ]
      })
    • 现在跳转时浏览器的地址栏已经有了参数id了(成功传参),那么我们如何在用户详情页获取传过来的这个id呢?
      推荐在路由规则里使用props传参,在props里接收路由传过来的参数:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      // 创建路由对象
      const router = new VueRouter({
      // 路由规则数组
      routes: [
      {
      path: '/',
      component: App,
      redirect: '/users',
      children: [
      { path: '/users', component: Users },
      { path: '/userInfo/:id', component: UserInfo, props: true },
      { path: '/rights', component: Rights },
      { path: '/goods', component: Goods },
      { path: '/orders', component: Orders },
      { path: '/settings', component: Settings }
      ]
      }
      ]
      })
    • 接下来我们在UserInfo组件中定义一个props来接收对应的数据
      定义前:
      1
      2
      3
      4
      5
      const UserInfo = {
      template: `<div>
      <h5>用户详情页</h5>
      </div>`
      }
      定义后:
      1
      2
      3
      4
      5
      6
      const UserInfo = {
      props: ['id'],
      template: `<div>
      <h5>用户详情页(用户id:{{id}})</h5>
      </div>`
      }
  • 实现编程式导航的路由后退功能
    除了浏览器的返回键,我们可以在用户详情页中添加一个button按钮实现后退

    • 添加按钮
      1
      2
      3
      4
      5
      6
      7
      const UserInfo = {
      props: ['id'],
      template: `<div>
      <h5>用户详情页(用户id:{{id}})</h5>
      <button>后退</button>
      </div>`
      }
    • 为按钮绑定单击事件 @click="goback()"
      事件处理函数 goback() 中用编程式导航的 go 函数给它一个 -1 就可以实现后退了
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      const UserInfo = {
      props: ['id'],
      template: `<div>
      <h5>用户详情页(用户id:{{id}})</h5>
      <button @click="goback()">后退</button>
      </div>`,
      methods: {
      goback() {
      // 实现后退功能
      this.$router.go(-1)
      }
      }
      }

》分析回顾

现在这个案例实现了,让我们回顾一下全部步骤:

  1. 抽离并渲染 App 根组件
  2. 将左侧菜单改造为路由链接
  3. 创建左侧菜单对应的右侧路由组件
  4. 在右侧主体区域添加路由占位符
  5. 添加子路由规则
  6. 通过路由重定向默认渲染用户组件
  7. 渲染用户列表数据
  8. 编程式导航跳转到用户详情页
  9. 实现后退功能

完整案例源码如下:

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>基于vue-router的案例</title>
<style type="text/css">
html,
body,
#app {
margin: 0;
padding: 0px;
height: 100%;
}
.header {
height: 50px;
background-color: #545c64;
line-height: 50px;
text-align: center;
font-size: 24px;
color: #fff;
}
.footer {
height: 40px;
line-height: 40px;
background-color: #888;
position: absolute;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
}
.main {
display: flex;
position: absolute;
top: 50px;
bottom: 40px;
width: 100%;
}
.content {
flex: 1;
text-align: center;
height: 100%;
}
.left {
flex: 0 0 20%;
background-color: #545c64;
}
.left a {
color: white;
text-decoration: none;
}
.right {
margin: 5px;
}
.btns {
width: 100%;
height: 35px;
line-height: 35px;
background-color: #f5f5f5;
text-align: left;
padding-left: 10px;
box-sizing: border-box;
}
button {
height: 30px;
background-color: #ecf5ff;
border: 1px solid lightskyblue;
font-size: 12px;
padding: 0 20px;
}
.main-content {
margin-top: 10px;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
ul li {
height: 45px;
line-height: 45px;
background-color: #a0a0a0;
color: #fff;
cursor: pointer;
border-bottom: 1px solid #fff;
}

table {
width: 100%;
border-collapse: collapse;
}

td,
th {
border: 1px solid #eee;
line-height: 35px;
font-size: 12px;
}

th {
background-color: #ddd;
}
</style>
<script src="./lib/vue_2.5.22.js"></script>
<script src="./lib/vue-router_3.0.2.js"></script>
</head>
<body>
<!-- 要被Vue实例所控制的区域 -->
<div id="app">
<!-- 路由占位符 -->
<router-view></router-view>
</div>

<script>
// 定义APP根组件
const App = {
template: `
<div>
<!-- 头部区域 -->
<header class="header">传智后台管理系统</header>
<!-- 中间主体区域 -->
<div class="main">
<!-- 左侧菜单栏 -->
<div class="content left">
<ul>
<li><router-link to="/users">用户管理</router-link></li>
<li><router-link to="/rights">权限管理</router-link></li>
<li><router-link to="/goods">商品管理</router-link></li>
<li><router-link to="/orders">订单管理</router-link></li>
<li><router-link to="/settings">系统设置</router-link></li>
</ul>
</div>
<!-- 右侧内容区域 -->
<div class="content right"><div class="main-content">
<router-view />
</div></div>
</div>
<!-- 尾部区域 -->
<footer class="footer">版权信息</footer>
</div>`
}

// 创建左侧菜单对应的右侧路由组件
const Users = {
data() {
// 返回一个数据对象,返回的数据对象是用户列表的数组
return {
userlist: [
{ id: 1, name: '张三', age: 17 },
{ id: 2, name: '李四', age: 18 },
{ id: 3, name: '王五', age: 19 },
{ id: 4, name: '赵六', age: 20 }
]
}
},
methods: {
goDetail(id) {
// 查看是否拿到参数:
// console.log(id)
// 通过编程式导航实现页面跳转:
this.$router.push('/userInfo/' + id)
}
},
template: `<div>
<h3>用户管理区域</h3>
<table>
<thead>
<tr><th>编号</th><th>姓名</th><th>年龄</th><th>操作</th></tr>
</thead>
<tbody>
<tr v-for="item in userlist" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td><a href="javascript:;" @click="goDetail(item.id)">详情</a></td>
</tr>
</tbody>
</table>
</div>`
}

const UserInfo = {
props: ['id'],
template: `<div>
<h5>用户详情页(用户id:{{id}}</h5>
<button @click="goback()">后退</button>
</div>`,
methods: {
goback() {
// 实现后退功能
this.$router.go(-1)
}
}
}

const Rights = { template: `<div>
<h3>权限管理区域</h3>
</div>` }
const Goods = { template: `<div>
<h3>商品管理区域</h3>
</div>` }
const Orders = { template: `<div>
<h3>订单管理区域</h3>
</div>` }
const Settings = { template: `<div>
<h3>系统设置区域</h3>
</div>` }


// 创建路由对象
const router = new VueRouter({
// 路由规则数组
routes: [
{
path: '/',
component: App,
redirect: '/users',
children: [
{ path: '/users', component: Users },
{ path: '/userInfo/:id', component: UserInfo, props: true },
{ path: '/rights', component: Rights },
{ path: '/goods', component: Goods },
{ path: '/orders', component: Orders },
{ path: '/settings', component: Settings }
]
}
]
})


const vm = new Vue({
el: '#app',
router
})
</script>

</body>
</html>

特别感谢: