Vue的前端路由
一 路由基本概念
路由的本质就是对应关系。
路由可分为:
- 后端路由:URL请求地址与服务器资源之间的对应关系。

- 前端路由:用户事件与事件处理函数之间的对应关系。

二 手写路由
<!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="./js/vue.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":zhuye,
"keji":keji,
"caijing":caijing,
"yule":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>
三 Vue-Router使用
3.1 基本使用步骤
路由的使用一共分为六步
<!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="./js/vue_2.5.22.js"></script>
<!-- 1.导入Vue-router组件 -->
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id="app">
<!-- 2.添加路由链接 -->
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
<!-- 3.路由占位符 -->
<router-view></router-view>
</div>
<script>
// 4.定义路由组件
var User = {
template: '<h1>用户组件</h1>'
};
var Register = {
template: '<h1>注册组件</h1>'
};
// 5.配置路由规则
var router = new VueRouter({
routes: [
{path:"/user",component:User},
{path:"/register",component:Register}
]
});
// 6.路由挂载到Vue
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.2 路由重定向
路由重定向操作,将访问根路径时候,重定向到访问/user路径
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id="app">
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
<router-view></router-view>
</div>
<script>
var User = {
template: '<h1>用户组件</h1>'
};
var Register = {
template: '<h1>注册组件</h1>'
};
var router = new VueRouter({
routes: [
// 路由重定向操作,将访问根路径时候,重定向到访问/user路径
{path:"/",redirect:"/user"},
{path:"/user",component:User},
{path:"/register",component:Register}
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.3 嵌套路由
在Register这个父组件中,加入Tab1和Tab2两个子组件
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id="app">
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
<router-view></router-view>
</div>
<script>
var User = {
template: '<h1>用户组件</h1>'
};
var Register = {
template: `
<div>
<h1>注册组件</h1>
<hr/>
<router-link to="/register/tab1">Tab1</router-link>
<router-link to="/register/tab2">Tab2</router-link>
<router-view></router-view>
</div>
`
};
var Tab1 = {
template: "<h3>Tab1</h3>"
};
var Tab2 = {
template: "<h3>Tab2</h3>"
};
var router = new VueRouter({
routes: [
{path:"/",redirect:"/user"},
{path:"/user",component:User},
{path:"/register",component:Register,children:[
{path:"/register/tab1",component:Tab1},
{path:"/register/tab2",component:Tab2}
]}
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.4 动态路由
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<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-view></router-view>
</div>
<script>
var User = {
//获取动态的路由数据
template: '<h1>用户组件,id:{{$route.params.id}}</h1>'
};
var router = new VueRouter({
routes: [
//动态部分
{path:"/user/:id",component:User},
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.5 路由组件传递参数
$route与对应路由高度耦合,需要进行改进props的形式解除组件和路由之间的耦合关系。
- props的值为布尔类型(常用,用于接收路径中的动态参数)
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<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-view></router-view>
</div>
<script>
var User = {
//props接收参数
props:["id"],
template: '<h1>用户组件,id:{{id}}</h1>'
};
var router = new VueRouter({
routes: [
//增加props的布尔值开启
{path:"/user/:id",component:User,props:true},
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
- props的值为对象类型(用于传递静态参数,此时无法传递路径中的动态参数)
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<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-view></router-view>
</div>
<script>
var User = {
//props接收静态参数
props:["uname","age"],
template: '<h1>用户组件,姓名:{{uname}},年龄:{{age}}</h1>'
};
var router = new VueRouter({
routes: [
//传递静态参数
{path:"/user/:id",component:User,props:{uname:"yorick",age:23}},
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
- props的值为函数类型(既可以传递静态参数,也可以传递动态参数)
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<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-view></router-view>
</div>
<script>
var User = {
//props接收静态和动态参数
props:["id","uname","age"],
template: '<h1>用户组件,id:{{id}},姓名:{{uname}},年龄:{{age}}</h1>'
};
var router = new VueRouter({
routes: [
//传递静态参数和动态参数
{path:"/user/:id",component:User,props:route=>({uname:"yorick",age:"23",id:route.params.id})},
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.6 命名路由
通过给路由起名字,使用该名称来作为链接的传递形式。
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<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-view></router-view>
</div>
<script>
var User = {
props:["id"],
template: '<h1>用户组件,id:{{id}}</h1>'
};
var router = new VueRouter({
routes: [
//添加路由的name
{name:"user",path:"/user/:id",component:User,props:true},
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
3.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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id="app">
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
<router-view></router-view>
</div>
<script>
var User = {
template: `
<div>
<h1>用户组件</h1>
<button @click="goRegister">跳转到注册页面</button>
</div>
`,
methods: {
goRegister: function(){
this.$router.push("/register");
}
}
};
var Register = {
template: `
<div>
<h1>注册组件</h1>
<button @click="goBack">回退</button>
</div>
`,
methods: {
goBack: function(){
this.$router.go(-1);
}
}
};
var router = new VueRouter({
routes: [
{path:"/user",component:User},
{path:"/register",component:Register}
]
});
var vm = new Vue({
el:"#app",
data:{},
router:router
});
</script>
</body>
</html>
四 案例
功能点:
- 抽离并渲染App根组件
- 将左侧菜单改造为路由链接
- 创建左侧菜单对应的路由组件
- 在右侧主题区域添加路由占位符
- 添加子路由规则
- 通过路由重定向默认渲染用户组件
- 渲染用户列表数据
- 编程式导航跳转到用户详情页
- 实现后退功能
<!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="./js/vue_2.5.22.js"></script>
<script src="./js/vue-router_3.0.2.js"></script>
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<script>
var 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>`
}
var Users = {
data: function(){
return {
userList:[
{id:1,username:"Yorick",age:23},
{id:2,username:"Tom",age:24},
{id:3,username:"Jerry",age:25},
{id:4,username:"Smith",age:26}
]
}
},
template: `
<div>
<h1>用户管理</h1>
<table>
<thead>
<tr>
<th>编号</th>
<th>用户名</th>
<th>年龄</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr :key="item.id" v-for="item in userList">
<td>{{item.id}}</td>
<td>{{item.username}}</td>
<td>{{item.age}}</td>
<td><a href="javascript:;" @click="userDetail(item.id)">操作</a></td>
</tr>
</tbody>
</table>
</div>
`,
methods:{
userDetail: function(id){
this.$router.push("/userDetail/"+id);
}
}
}
var UserDetail = {
props:["id"],
template: `
<div>
<h2>用户详情页</h2>
<h3>用户编号:{{id}}</h3>
<button @click="goBack">回退</button>
</div>
`,
methods: {
goBack: function(){
this.$router.go(-1);
}
}
}
var Rights = {
template: `
<div>
<h1>权限管理</h1>
</div>
`
}
var Goods = {
template: `
<div>
<h1>商品管理</h1>
</div>
`
}
var Orders = {
template: `
<div>
<h1>订单管理</h1>
</div>
`
}
var Settings = {
template: `
<div>
<h1>系统管理</h1>
</div>
`
}
var router = new VueRouter({
routes:[
{path:"/",component:App,redirect:"/users", children:[
{path:"/users",component:Users},
{path:"/userDetail/:id",component:UserDetail,props:true},
{path:"/rights",component:Rights},
{path:"/goods",component:Goods},
{path:"/orders",component:Orders},
{path:"/settings",component:Settings}
]}
]
})
var vm = new Vue({
el:"#app",
router:router
})
</script>
</body>
</html>
网友评论