什么是路由?
-
路由就是通过
url
的地址去请求的资源,这个地址和资源有一种对应关系, 就被叫做路由 -
路由分为前端路由和后端路由
- 前端路由:通过
hash值
(锚链接)的变化实现 - 后端路由:在服务器中实现,通过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>
</head>
<body>
<div id="app">
<div>
<a href="#/nationNews">国内新闻</a>
<a href="#/foreignNews">国际新闻</a>
<a href="#/hotNews">热点新闻</a>
<a href="#/playNews">娱乐新闻</a>
</div>
<hr />
<component :is="componentId"></component>
</div>
</body>
<script src="./lib/vue_2.5.22.js"></script>
<script>
//点击a链接,就会改变url中的hash值,当hash发生变化时触发
window.onhashchange = function () {
console.log(location.hash)//获取hash值
switch (location.hash.slice(1)) {//根据不同hash值实现路由切换
case '/nationNews':
vm.componentId = 'nation-news'
break;
case '/foreignNews':
vm.componentId = 'foreign-news'
break;
case '/hotNews':
vm.componentId = 'hot-news'
break;
case '/playNews':
vm.componentId = 'play-news'
break;
}
}
//国内新闻组件
var nationNews = {
template: `
<div><h1>国内新闻</h1></div>
`
}
//国际新闻组件
var foreignNews = {
template: `
<div><h1>国际新闻</h1></div>
`
}
//热点新闻组件
var hotNews = {
template: `
<div><h1>热点新闻</h1></div>
`
}
//娱乐新闻组件
var playNews = {
template: `
<div><h1>娱乐新闻</h1></div>
`
}
//创建vue实例
var vm = new Vue({
el: "#app",
data: {
componentId: 'nation-news'//默认显示国内新闻
},
//注册组件
components: {
'nation-news': nationNews,
'foreign-news': foreignNews,
'hot-news': hotNews,
'play-news': playNews
}
})
</script>
</html>
页面显示结果如下
Vue-Router
- 它是一个
Vue.js
官方提供的路由管理器。是一个功能更加强大的前端路由器 - 可以一起方便的实现
SPA(single page web application)
,单页应用程序应用程序的开发
Vue-Router的特性
- 支持H5历史模式或者hash模式
- 支持嵌套路由
- 支持路由参数
- 支持编程式路由
- 支持命名路由
- 支持路由导航守卫
- 支持路由过渡动画特效
- 支持路由懒加载
- 支持路由滚动行为
Vue-router使用步骤
- 下载
vue-router
插件,https://router.vuejs.org/zh/installation.html - 引入vue-router
-注意:要放置在vue.js后
- 添加路由链接
<router-link>
- 添加路由填充位
<router-view>
- 定义路由组件
- 配置路由
- 挂载路由到vue实例中
示例代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<!-- 使用router-link代替a标签,router-link默认是a标签 to属性默认是href属性 -->
<router-link to="/nationNews">国内新闻</router-link>
<router-link to="/foreignNews">国际新闻</router-link>
<router-link to="/hotNews">热点新闻</router-link>
<router-link to="/playNews">娱乐新闻</router-link>
</div>
<hr />
<!-- 路由填充位,组件要显示的位置 -->
<router-view />
</div>
</body>
<!-- 引入vue.js -->
<script src="./lib/vue_2.5.22.js"></script>
<!-- 引入vue-router.js必须放在vue.js后 -->
<script src="./lib/vue-router_3.0.2.js"></script>
<script>
//国内新闻组件
var nationNews = {
template: `
<div><h1>国内新闻</h1></div>
`
}
//国际新闻组件
var foreignNews = {
template: `
<div><h1>国际新闻</h1></div>
`
}
//热点新闻组件
var hotNews = {
template: `
<div><h1>热点新闻</h1></div>
`
}
//娱乐新闻组件
var playNews = {
template: `
<div><h1>娱乐新闻</h1></div>
`
}
//创建vue-router实例
//这里的VueRouter是vue-router.js中提供的
var router = new VueRouter({
//配置路由规则,因为有多个路由,所以routes属性是一个数组,存放的是路由对象
routes: [
//设置默认页面,redirect表示要被重定向的新地址,这里默认重定向到国内新闻
{ path: '/', redirect: '/nationNews' },
//path页面的地址,component组件对象
{ path: '/nationNews', component: nationNews },
{ path: '/foreignNews', component: foreignNews },
{ path: '/hotNews', component: hotNews },
{ path: '/playNews', component: playNews },
]
})
//创建vue实例
var vm = new Vue({
el: "#app",
//将router挂载到vue实例中
router: router
})
</script>
</html>
嵌套路由
- 有时候可能在某一个组件中又包含着子级路由链接,这时需要使用嵌套路由实现
示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<!-- 使用router-link代替a标签,router-link默认是a标签 to属性默认是href属性,to属性的值会被渲染为#开头的hash地址 -->
<router-link to="/nationNews">国内新闻</router-link>
<router-link to="/foreignNews">国际新闻</router-link>
<router-link to="/hotNews">热点新闻</router-link>
<router-link to="/playNews">娱乐新闻</router-link>
</div>
<hr />
<!-- 路由填充位,组件要显示的位置 -->
<router-view />
</div>
</body>
<!-- 引入vue.js -->
<script src="./lib/vue_2.5.22.js"></script>
<!-- 引入vue-router.js必须放在vue.js后 -->
<script src="./lib/vue-router_3.0.2.js"></script>
<script>
//国内新闻组件
//只做演示,这里只写一个嵌套路由
var nationNews = {
template: `
<div>
<h1>国内新闻</h1>
<router-link to="/nationNews/heatRanking">热度排行榜</router-link>
<router-view/>
</div>
`
}
//国际新闻组件
var foreignNews = {
template: `
<div><h1>国际新闻</h1></div>
`
}
//热点新闻组件
var hotNews = {
template: `
<div><h1>热点新闻</h1></div>
`
}
//娱乐新闻组件
var playNews = {
template: `
<div><h1>娱乐新闻</h1></div>
`
}
//热度排行榜组件
var heatRanking = {
template: `
<div><h2>热度排行榜</h2></div>
`
}
//创建vue-router实例
//这里的VueRouter是vue-router.js中提供的
var router = new VueRouter({
//配置路由规则,因为有多个路由,所以route属性是一个数组,存放的是路由对象
routes: [
//设置默认页面,redirect表示要被重定向的新地址,这里默认重定向到国内新闻
{ path: '/', redirect: '/nationNews' },
//path页面的地址,component组件对象
{
path: '/nationNews',
component: nationNews,
children: [{//children属性仍然是一个数组,存放的是路由对象
path: 'heatRanking',//这种方式前面不能带'/',还有另一种方式:/nationNews/heatRanking
component: heatRanking
}]
},
{ path: '/foreignNews', component: foreignNews },
{ path: '/hotNews', component: hotNews },
{ path: '/playNews', component: playNews },
]
})
//创建vue实例
var vm = new Vue({
el: "#app",
//将router挂载到vue实例中
router: router
})
</script>
</html>
页面显示结果如下
动态路由
先看一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<router-link to="/user">显示用户列表</router-link>
</div>
<!-- 路由填充位,组件要显示的位置 -->
<router-view />
</div>
</body>
<!-- 引入vue.js -->
<script src="./lib/vue_2.5.22.js"></script>
<!-- 引入vue-router.js必须放在vue.js后 -->
<script src="./lib/vue-router_3.0.2.js"></script>
<script>
//用户列表
var user = {
template:
`
<div>
<h1>用户列表</h1>
<router-link to="/user/1">用户1</router-link>
<router-link to="/user/2">用户2</router-link>
<router-link to="/user/3">用户3</router-link>
<router-link to="/user/4">用户4</router-link>
<router-view/>
</div>
`
}
//用户1组件
var user1 = {
template: `
<div>
<h1>用户信息如下</h1>
<span>姓名:张三</span></br>
<span>性别:男</span></br>
<span>年龄:18</span></br>
</div>
`
}
//用户2组件
var user2 = {
template: `
<div>
<h2>用户信息如下</h2>
<span>姓名:李四</span></br>
<span>性别:男</span></br>
<span>年龄:19</span></br>
</div>
`
}
//用户3组件
var user3 = {
template: `
<div>
<h2>用户信息如下</h2>
<span>姓名:王丹</span></br>
<span>性别:女</span></br>
<span>年龄:20</span></br>
</div>
`
}
//用户4组件
var user4 = {
template: `
<div>
<h2>用户信息如下</h2>
<span>姓名:赵柳</span></br>
<span>性别:男</span></br>
<span>年龄:18</span></br>
</div>
`
}
//创建vue-router实例
//这里的VueRouter是vue-router.js中提供的
var router = new VueRouter({
//配置路由规则,因为有多个路由,所以route属性是一个数组,存放的是路由对象
routes: [
//path页面的地址,component组件对象
{
path: '/user',
component: user,
//children属性仍然是一个数组,存放的是路由对象
children: [
{
path: '1',//这种方式前面不能带'/',还有另一种方式:/user/1
component: user1
},
{
path: '2',//这种方式前面不能带'/',还有另一种方式:/user/2
component: user2
},
{
path: '3',//这种方式前面不能带'/',还有另一种方式:/user/3
component: user3
},
{
path: '4',//这种方式前面不能带'/',还有另一种方式:/user/4
component: user4
}
]
},
]
})
//创建vue实例
var vm = new Vue({
el: "#app",
//将router挂载到vue实例中
router: router
})
</script>
</html>
页面显示结果如下
-
从代码中可以发现几个问题
- 代码太冗余,大量重复代码
- 每添加一个路由链接就需要添加一个路由对象,并且模板都是一样的
- 如果有100个用户?需要添加100个吗?
为了解决这个问题,可以使用vue-router
中的动态路由解决
示例代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<div>
<router-link to="/user">显示用户列表</router-link>
</div>
<!-- 路由填充位,组件要显示的位置 -->
<router-view />
</div>
</body>
<!-- 引入vue.js -->
<script src="./lib/vue_2.5.22.js"></script>
<!-- 引入vue-router.js必须放在vue.js后 -->
<script src="./lib/vue-router_3.0.2.js"></script>
<script>
//用户列表,一般会调用后台接口遍历用户,这里不做演示
var user = {
template:
`
<div>
<h1>用户列表</h1>
<router-link to="/user/1">用户1</router-link>
<router-link to="/user/2">用户2</router-link>
<router-link to="/user/3">用户3</router-link>
<router-link to="/user/4">用户4</router-link>
<router-view/>
</div>
`
}
//用户信息组件
var userInfo = {
props: ["id"],//通过props获取参数,我们可以根据id查询用户信息再渲染到模板中,这里不做演示
template: `
<div>
<h1>用户信息如下</h1>
<span>用户id:{{id}}</span></br>
<span>姓名:张三</span></br>
<span>性别:男</span></br>
<span>年龄:18</span></br>
</div>
`
}
//创建vue-router实例
//这里的VueRouter是vue-router.js中提供的
var router = new VueRouter({
//配置路由规则,因为有多个路由,所以route属性是一个数组,存放的是路由对象
routes: [
//path页面的地址,component组件对象
{
path: '/user',
component: user,
//children属性仍然是一个数组,存放的是路由对象
children: [
//通过/:参数名 的形式传递参数
//如果props设置为true,route.params将会被设置为组件属性
{
path: ':id',//这种方式前面不能带'/'
component: userInfo,
props:true
},
]
},
]
})
//创建vue实例
var vm = new Vue({
el: "#app",
//将router挂载到vue实例中
router: router
})
</script>
</html>
页面显示结果如下:
- 这样一来,解决了以上问题,可以根据动态路由显示不同用户信息
补充
- prop还可以是对象,将prop设置为对象形式
props:{username:'李四',age:18}
- prop也可以是动态传参+对象,将prop设置为函数形式
props:(route)=>{
return {username:"jack",pwd:123,id:route.params.id}
}
命名路由
- 给路由取别名
const router = new VueRouter({
routes: [
{
path: '/user/:id',
name: 'user',
component: User
}
]
})
<router-link
//可以使用别名进行跳转
:to="{ name: 'user', params: { id: 1}}">用户1
</router-link>
编程式导航
页面导航有两种方式
- 声明式导航:通过点击链接的方式实现的导航
- 编程式导航:调用
js
的api
方法实现导航
vue-router
中的编程式导航
router.push()
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
router.go()
this.$router.go( n );//n为数字,参考history.go
// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
router.go(-1)