一、什么是路由
1、提到路由,一般会想到生活中常见的路由器,路由器主要用于连接多个逻辑上分开的网络,逻辑网络代表一个单独的网络或者一个子网,可以通过路由器功能来完成不同网络之间数据的传递。在Vue中也引入了路由的概念,因此,我们先来对程序开发中的路由进行简单地了解。
假如有一台提供 Web 服务的服务器的网络地址是localhost:8080,而该 Web 服务又提供了三个可供用户访问的页面
http://localhost:8080/regsiter
访问路径分别是 /、/login、/regsiter
简单的说,路由是根据不同的 url 地址展示不同的内容或页面
程序开发中的路由分为后端路由和前端路由。
2、后端路由
后端路由通过用户请求的URL分发到具体的处理程序,浏览器每次跳转到不同的URL,都会重新访问服务器。服务器收到请求后,将数据和模板组合,返回HTML页面,或者直接返回HTML模板,由前端JavaScript程序再去请求数据,使用前端模板和数据进行组合,生成最终的HTML页面。
后端路由的工作原理如下图所示。
当用户在浏览器中输入URL地址http://localhost:8080/login来访问“登陆”页面时,服务器就会收到这个请求找到相对应的处理程序,这就是路由的分发,这一功能是通过路由来实现的。
温馨提示:浏览器每访问一次新页面的时候,都要向服务器发送请求,然后服务器会响应请求,返回新页面给浏览器,在这个过程中会有一定的网络延迟。
3、前端路由
前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做。对于单页面应用(SPA)来说,主要通过URL中的hash(#号)来实现不同页面之间的切换。hash有一个特点,就是HTTP请求中不会包含hash相关的内容,所以单页面程序中的页面跳转主要用hash来实现。
前端路由的工作原理如下图所示。
上图中,index.html后面的“#/home”是hash方式的路由,由前端路由来处理,将hash值与页面中的组件对应,当hash值为“#/home”时,就显示“首页”组件。
二、前端路由的基本原理
1、案例说明
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>前端路由的基本原理</title>
</head>
<body>
<a href="#/login">登陆界面</a>
<a href="#/register">注册界面</a>
<div id="app"></div>
<script>
var appDiv= document.getElementById("app");
window.onhashchange=function(){ ///监听onhashchange事件,用于改变url
console.log(location.hash)
switch(location.hash){ //window.location.hash 获取当前的hash值
case '#/login': appDiv.innerHTML="<h2>我是登陆界面</h2>"
break;
case '#/register': appDiv.innerHTML="<h2>我是注册界面</h2>"
break;
default:break;
}
}
</script>
</body>
</html>
当你点击登陆界面时,浏览器地址栏的hash会变成#/login
这里的hash就是指url后的#号以及后面的字符,比如说"https://www.baidu.com/#home",其中“#home”就是hash值。
三、Vue-router
1、vue-router工作原理
单页面应用(SPA)的核心思想之一,它在加载页面时,不会加载整个页面,只会更新视图(即某个指定的容器中的内容)。
在实现单页面前端路由时,提供了两种方式,分别是hash模式和history模式,根据mode参数来决定采用哪一种方式。
- hash模式
vue-router默认为hash模式,使用URL的hash来模拟一个完整的URL,当URL改变时,页面不会重新加载。#就是hash符号,中文名为哈希符或者锚点,在hash符号后的值,称为hash值。
路由的hash模式是利用了window可以监听onhashchange事件来实现的,也就是说hash值是用来指导浏览器动作的,对服务器没有影响,HTTP请求中也不会包括hash值,同时每一次改变hash值,都会在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上一个位置。所以,hash模式是根据hash值来发生改变,根据不同的值,渲染指定DOM位置的不同数据。
- history模式
history模式不会出现#号比较美观,这种模式充分利用history.pushState()来完成URL的跳转而且无须重新加载页面。使用history模式时,需要在Vue手脚架里的main.js 文件中增加mode:'history',示例代码如下。
// main.js文件
const router = new VueRouter({
mode: 'history',
routes: [...]
})
2、 vue-router基本使用
vue-router可以实现当用户单击页面中的A按钮时,页面显示内容A;单击B按钮时,页面显示内容B。换言之,用户单击的按钮和页面显示的内容,两者是映射的关系。
学习vue-router的基本使用前,首先了解路由中3个基本的概念:route、routes、router。
route :表示它是一条路由,单数形式
routes:表示它是一组路由,把route的每一条路由组合起来,形成一个数组
router:表示它是一个机制,充当管理路由的管理者角色
接下来,我通过一个案例演示vue-router的使用。
①vue.js下载地址:安装 — Vue.js , vue-router.js下载地址:安装 — Vue-router.js,然后Ctrl+s保存Vue-router.js文件即可。首先从官方网站获取vue.js和vue-router.js文件,保存到文件目录中。其次创建html文件,并在文件中引入这两个文件,引入文件的代码如下。
<script src="vue.js"></script>
<script src="vue-router.js"></script>
必须先引入vue.js,再引入vue-router.js,引入顺序不能颠倒,因为vue-router需要在全局Vue的实例上挂载vue-router相关的属性。
②编写html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vuerouter的使用</title>
</head>
<body>
<div id="app">
<!-- 这里最终会渲染全局组件 -->
</div>
<!-- 1、先引入vue.js 注意:引入顺序不能颠倒 -->
<script src="lib/vue.js"></script>
<!-- 2、引入vue-router.js -->
<script src="lib/vue-router.js"></script>
</body>
</html>
③让vue使用VueRouter组件
Vue.use(VueRouter);
④创建路由对象
var r=new VueRouter({ });
⑤配置路由对象
routes:[
{ //路由匹配规则 path:路径 component:组件
path:"/login",
component:Login
},
{
path:"/register",
component:Register
}
]
⑥创建需要的组件
var Login={
template:'<h2>我是登录组件</h2>'
}
var Register={
template:'<h2>我是注册组件</h2>'
}
⑦VueRouter 抛出两个全局组件 router-link相当于a链接 router-view相当于一个出口
var App={
template:`<div>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>`
}
⑧声明路由
new Vue({
router:r,
})
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vuerouter的使用</title>
</head>
<body>
<div id="app">
<!-- 这里最终会渲染全局组件 -->
</div>
<!-- 1、先引入vue.js 注意:引入顺序不能颠倒 -->
<script src="lib/vue.js"></script>
<!-- 2、这是动态引入vue-router.js -->
<script src="lib/vue-router.js"></script>
<script>
//3、让vue使用VueRouter组价
Vue.use(VueRouter);
//6、创建需要的组件
var Login = {
template: '<h2>我是登录组件</h2>'
}
var Register = {
template: '<h2>我是注册组件</h2>'
}
//4、创建路由对象
var r = new VueRouter({
//5、配置路由对象
routes: [
{ //路由匹配规则 path:路径 component:组件
path: "/login",
component: Login
},
{
path: "/register",
component: Register
}
]
})
//7、VueRouter 抛出两个全局组件 router-link相当于a链接 router-view相当于一个出口
var App = {
template: `<div>
<router-link to="/login">登录</router-link>
<router-link to="/register">注册</router-link>
<router-view></router-view>
</div>`
}
new Vue({
el: "#app",
//8、声明路由
router: r,
template: "<App/>", //这行代码,我理解为将它挂载到Dom节点"#app"的div上,并全局组件渲染出来
data: {
},
components: {
App //挂子
}
})
</script>
</body>
</html>
在浏览器中打开文件,会看到页面中有“登录”“注册”这4个字,单击“登录”,就会在下方出现“我是登录组件”,单击“注册”则显示“我是注册组件”,效果如下图所示。
3、路由对象属性
①路由对象(route object)表示当前激活的路由的状态信息,包含了当前
URL解析得到的信息,还有URL匹配到的路由记录。路由对象是不可变的,每次成功地导航后都会产生一个新的对象。
②this.$router表示全局路由器对象,项目中通过router路由参数注入路由之后,在任何一个页面都可以通过此属性获取到路由器对象,并调用其push()、go()等方法。this.$route表示当前正在用于跳转的路由对象,可以访问其name、path、query、params等属性。
属性名 | 类型 | 说明 |
$route.path | String | 对应当前路由的名字 |
$route.query | Object | 一个{key:value}对象,表示 URL查询参数 |
$route.params | Object | 一个{key:value}对象,路由转跳携带参数 |
$route.hash | String | 在history模式下获取当前路由的hash值(带#),如果没有hash值,则为空字符串 |
$route.fullPath | String | 完成解析后的URL,包含查询参数和hash的完整路径 |
$route.name | String | 当前路由的名称 |
$route.matched | Array | 路由记录,当前路由下路由声明的所有信息,从父路由(如果有)到当前路由为止 |
$route.redirectedFrom | String | 如果存在重定向,即为重定向来源的路由 |
四、命名路由
1、命名路由,可以在创建Router实例的时候,在 routes 中给某个路由设置名称name值。通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候,通过路由的名称取代路径地址直接使用。像这种命名路由的方式,无论path多长、多烦琐,都能直接通过name来引用,十分方便。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>命名路由</title> <!-- 当你点击登陆/注册的文本时,地址栏的地址也会发生变化 -->
</head>
<body>
<!-- 1、先引入vue.js 再引入vue-router.js --> 注意:引入js的顺序不能颠倒
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<div id="app">
<h1>{{msg}}</h1>
<App />
</div>
<script>
//2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter)
//4、创建两个组件 一个是登陆 一个是注册
var Login = {
template: '<h2>我是登陆界面</h2>'
}
var Register = {
template: '<h2>我是注册界面</h2>'
}
//3、创建VueRouter对象 router routes route
var r = new VueRouter({
routes: [
//路由匹配规则 path路由引用路径 component导出的组件 name 名字
{ path: '/login', component: Login, name: 'login' },
{ path: '/register', component: Register, name: 'register' }
]
})
//5、通过App组件渲染出路由页面
var App = {
// router-link 相当于 a链接 里面一个to属性相当于href
// router-view 相当于输出页面
// 当使用对象作为路由的时候,to前面要加一个冒号,表示绑定
template: `
<div>
<router-link :to="{name:'login'}" tag="div">登陆界面</router-link>
<router-link :to="{name:'register'}" tag="div">注册界面</router-link>
<router-view></router-view>
</div>
`
}
new Vue({
el: '#app',
data: {
msg: '前端路由命名'
},
components: {
App
},
//声明路由
router: r
})
</script>
</body>
</html>
五、路由参数
1、路由参数指的是地址栏的链接后带有的参数(本人这样理解),一般我们地址栏有两种形式:
①xxx.html/user/discover/toplist params参数params参数(带有冒号传参) 路由userQ
②xxx.html/user?username=abc&password=123 query参数 路由userP
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>路由参数</title>
</head>
<body>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<div id="app">
<h1>看地址栏路径</h1>
<!-- 路由的渲染 -->
<!-- 1、params参数 --> <!-- router-link 相当于 a链接 里面一个to属性相当于href -->
<router-link :to="{name:'userQ',params:{id:'罗翔',zhiye:'厚大律师'}}">P参数<br><br></router-link>
<!-- 2、query参数 -->
<router-link :to="{name:'userP',query:{username:'张三',waihao:'法外狂徒'}}">Q参数<br><br></router-link>
<!-- 路由的出口, 相当于输出页面 -->
<router-view></router-view>
</div>
<script>
// 2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter);
// 3、创建两个组件,用于在页面输出,方便自己观察路径的路由参数
var UserQ ={
template:'<div><h2>params参数, id:{{this.$route.params.id}}, zhiye(职业):{{this.$route.params.zhiye}}</div></h2>'
}
var UserP ={
template:'<div><h2>query参数, 路由路径是{{this.$route.path}}, 我的路由名字是{{this.$route.name}}, username(名字):{{this.$route.query.username}},waihao(外号):{{this.$route.query.waihao}}</h2></div>'
}
// 4、创建VueRouter对象
var router = new VueRouter({
routes:[
//5、路由匹配 path路由引用路径 component导出的组件 name路由的名字
{
path:'/user/:id/:zhiye', //param参数
name:'userQ',
component:UserQ
},
{
path:'/user', //query参数
name:'userP',
component:UserP
}
]
})
new Vue({
el:'#app',
// 6、声明路由
router:router
})
</script>
</body>
</html>
六、嵌套路由
1、是否是嵌套路由主要是由页面结构来决定的,嵌套路由就是在路由里面嵌套它的子路由。
嵌套子路由的关键属性是children,children也是一组路由,每一个子路由里面可以嵌套多个组件,子组件又有路由导航和路由容器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>嵌套路由例</title>
</head>
<body>
<!--
需求: 飞行员组件 /flyer
新城组件 /flyer/xincheng
新城组件内容 Xincheng
大古组件 /flyer/dagu
大古组件内容 Dagu
坠机组件 /zhuiji
坠机数量组件内容 Zhuiji
-->
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<div id="app">
<!-- 路由的渲染 -->
<router-link to="/flyer">飞行员</router-link>   |  
<router-link to="/zhuiji">坠机</router-link>
<!-- 路由的出口 -->
<router-view></router-view>
</div>
<script>
// 2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter);
// 3、创建组件,用于在页面输出
var Flyer = {
template: `
<div>
<h1>亡牌飞行员</h1>
<router-link to="/flyer/xincheng">新城</router-link>    
<router-link to="/flyer/dagu">大古</router-link>
<router-view/>
</div>
`
}
var Zhuiji = {
template: '<div><h2>坠机数量</h2><img width="300px" height="300px" src="https://pics4.baidu.com/feed/0dd7912397dda144cf32bbb95908eda50df486cd.jpeg?token=9974dd405fe9ebb187dd7a5ccb1cb161"></div>'
}
var Xincheng = {
template: '<div><h2>我是亡牌飞行员——新城</h2></div>'
}
var Dagu = {
template: '<div><h2>我是亡牌飞行员——大古</h2></div>'
}
//4、创建VueRouter对象
var r = new VueRouter({
routes: [
//路由匹配 path路由引用路径 component导出的组件 name路由的名字
{ path: '/', redirect: 'flyer' }, //路由重定向
{
path: '/flyer',
component: Flyer,
// 子路由(children)前不需要加'/',否则永远以根路径开始请求,不方法用户理解url地址
children: [
{ path: 'xincheng', component: Xincheng },
{ path: 'dagu', component: Dagu }
]
},
{ path: '/zhuiji', component: Zhuiji }
]
})
new Vue({
el: '#app',
// 6、声明路由
router: r
})
</script>
</body>
</html>
七、动态路由匹配
1、我们经常需要把某种模式匹配到所有的路由,全都映射到同个组件。例如,我们有一本 Book 组件,对于所有 id 各不相同的书,都要使用这个组件来渲染。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态路由匹配</title>
</head>
<body>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<div id="app">
<!-- 1、路由的渲染 -->
<!-- 在组件中传入不同的id, 就能动态匹配路由, 不同用户id展示不同内容,但是全都映射到同个组件, 达到组件的重复使用, 同一个Book组件传入不同的id(1 2 3) -->
<router-link to="/book/1">Book1</router-link>
<router-link to="/book/2">Book2</router-link>
<router-link to="/book/3">Book3</router-link>
<router-link to="/name">Name</router-link>
<!-- 路由的出口 -->
<router-view></router-view>
</div>
<script>
// 2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter);
// 3、创建组件,用于在页面输出
var Book = {
template: '<h1>Book 组件 -- 用户id为: {{$route.params.id}}</h1>', // 当匹配到一个路由时,参数值会被设置到this.$route.params方法中,可以在每个组件内使用这个方法接受动态的id值。简单地说,组件中通过this.$route.params就能拿到id值。
// watch监听路由变化($route对象的变化)
watch: {
$route(to, from) {
console.log(to); //去的路由
console.log(from); //来的路由
}
},
created() {
console.log('生命周期钩子 . Book');//控制台打印出来
}
}
var Name = {
template: '<h1>Name 组件</h1>',
created() {
console.log('生命周期钩子 . Name');//控制台打印出来
}
}
//4、创建VueRouter路由实例对象
var router = new VueRouter({
routes: [
{ path: '/', redirect: '/book' },//路由重定向
// 我们可以使用“动态路径参数”来达到这个效果 ,一个“路径参数”使用冒号 : 标记。
{ path: '/book/:id', component: Book },
{ path: '/name', component: Name }
]
})
new Vue({
el: '#app',
// 5、声明路由
router: router
})
</script>
</body>
</html>
注意:当使用路由参数时,例如从 /book/1导航到 /book/2,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。这也意味着组件的生命周期钩子不会再被调用。但是如果复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route对象。有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。
八、编程式导航
1、除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。
声明式 编程式
<router-link :to="..."> router.push(...)
导航到不同的位置
在 Vue 实例中,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。
想要导航到不同的 URL,可以使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。
当你点击 <router-link> 时,内部会调用这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...) :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>编程式导航</title>
</head>
<body>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<div id="app">
<!-- 1、编写html代码(按钮) -->
<button @click="goStart">按钮显示params</button>
<router-view></router-view>
</div>
<script>
// 2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter);
// 3、创建组件
var User={
template:`<div><p>用户名是:{{this.$route.params.name}} 编号是:{{this.$route.params.id}} </p>
<button @click="goStart2">后退</button>
</div>`,
// 4、编写按钮的方法(按钮的功能方法)
methods:{
goStart2(){ //选择第45行的push(有历史记录),此函数才能生效
this.$router.go(-1) // go(-1)表示在浏览器中后退到上一步
}
}
}
// 4、创建VueRouter对象
var router=new VueRouter({
//5、路由匹配 path路由引用路径 component导出的组件 name路由的名字 带冒号后面的是参数
routes:[
{
path:'/user/:name/:id',
component:User,
name:'user'
}
]
})
new Vue({
el:'#app',
router:router,
methods:{
goStart(){
// 6、调用编程式导航 生成router-link
this.$router.push({name:'user',params:{name:'zhangsan',id:'1'}}) //有历史记录(push) 关于参数 params 和 query 的用法,请观看代码《路由参数》
//this.$router.replace({name:'user',params:{name:'zhangsan',id:'1'}}) //无历史记录(replace)
}
}
})
</script>
</body>
</html>
2、替换当前位置
它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。
也可以直接在传递给 router.push 的 routeLocation 中增加一个属性 replace: true :
router.push({ path: '/home', replace: true })
// 相当于
router.replace({ path: '/home' })
我们可以把上面的编程式导航案例代码中的
this.$router.push({name:'user',params:{name:'zhangsan',id:'1'}})
换成以下代码
this.$router.replace({name:'user',params:{name:'zhangsan',id:'1'}})
当你点击 按钮显示params 后,你就会发现无法返回到上一步,即使是点击 后退 按钮也一样,这是因为replace在导航时不会向 history 添加新记录。
3、横跨历史
该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)。
// 向前移动一条记录,与 router.forward() 相同
router.go(1)
// 返回一条记录,与router.back() 相同
router.go(-1)
// 前进 3 条记录
router.go(3)
// 如果没有那么多记录,静默失败
router.go(-100)
router.go(100)
九、命名视图
1、有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。
<router-view></router-view> <!-- 没有赋予名字,默认叫default -->
<div class="container">
<router-view name="left"></router-view>
<router-view name="right"></router-view>
</div>
2、一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用 components 配置 (带上 s):
{
path:'/home',
components:{
default:Header, // (router-view)视图名字:组件名字
left:Aside,
right:Main
}
}
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>命名视图</title>
<style>
h2{
margin: 0;
padding: 0;
}
.header{
background-color: antiquewhite;
height: 80px;
}
.container{
display: flex; /* 弹性布局 */
height: 200px;
}
.main{
background-color: aqua;
flex: 4;
}
.aside{
background-color: brown;
flex: 2;
}
</style>
</head>
<body>
<div id="app">
<!-- 需求:一个导航栏部分放在上面,一个侧边栏放在左边,一个主体内容放在后面 -->
<!-- 声明式导航 -->
<router-view></router-view> <!-- 没有赋予名字,默认叫default -->
<div class="container">
<router-view name="left"></router-view>
<router-view name="right"></router-view>
</div>
</div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script src="./node_modules/vue-router/dist/vue-router.js"></script>
<script>
Vue.use(VueRouter);
//头部组件
var Header={
template:'<h2 class="header">header头部区域</h2>'
}
//侧边栏组件
var Aside={
template:'<h2 class="aside">aside侧边栏区域</h2>'
}
//主体组件
var Main={
template:'<h2 class="main">main主体区域</h2>'
}
var router = new VueRouter({
routes:[
{
path:'/',
redirect:'/home'
},
{
path:'/home',
components:{
default:Header, // (router-view)视图名字:组件名字
left:Aside,
right:Main
}
}
]
})
new Vue({
el:'#app',
router,
})
</script>
</body>
</html>
十、全局前置路由守卫
1、路由守卫:保护路由的安全(权限)。
有些时候不是所有的导航项不是可以随便点击的,例如你在淘宝上需要登陆之后才能查看购物车。
首先要明确的是如果你想对购物车数据进行操作的话,必须处于登陆状态,不然随便来一个匿名用户就把你的购物车数据库删除了,你就只能立刻跑路了。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>meta和全局前/守卫</title>
</head>
<body>
<div id="app">
<!-- 1、编写导航条 -->
<router-link :to="{name:'index'}">首页</router-link>   |   <!--  是空白占位符 -->
<router-link :to="{name:'hot'}">热门</router-link>   |  
<router-link :to="{name:'message'}">消息</router-link>   |  
<router-link :to="{name:'login'}">登陆</router-link>   |  
<a href="javascript:void(0);" @click="clear">退出</a>   |  
<router-view></router-view>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 2、让vue对象使用vueRouter对象 axios sass VueRouter
Vue.use(VueRouter)
// 3、创建组件,用于在页面输出,方便自己观察地址栏的路由和点击了哪些东西
var Home = {
template: '<div><h3>我是首页</h3></div>'
}
var Hot = {
template: '<div><h3>我是热门</h3></div>'
}
var Message = {
template: '<div><h3>我是消息,有登陆者了,我显示出来</h3></div>'
}
// 登陆组件
var Login = {
data() {
return {
name: '',
password: ''
}
},
template: `
<div><h3>
用户名:<input type="text" v-model="name">
密码:<input type="password" v-model="password">
<input type="button" value="登陆" @click="login">
</h3></div>
`,
// 4、编写方法,用来存储用户数据
methods: {
login() {
//本地存储用户数据
localStorage.setItem("user", { name: this.name, password: this.password })
//编程式导航---跳到消息组件路由
this.$router.push({ name: "message" })
}
}
}
// 5、创建VueRouter对象
var router = new VueRouter({
routes: [
{ // 路由重定向
path: '/',
redirect: '/home'
},
{
path: '/home',
component: Home,
name: 'index'
},
{
path: "/hot",
component: Hot,
name: 'hot'
},
// 消息路由
{
path: '/message',
component: Message,
name: 'message',
// 6、编写路由元信息 给未来路由做权限控制, 全局路由守卫以这个做参照条件
meta: {
//表明用户访问消息组件需要判断登陆
auth: true
}
},
{
path: '/login',
component: Login,
name: 'login'
}
]
})
// 7、编写全局前置守卫
router.beforeEach((to, from, next) => { //to 我们要跳转的路由 from表示我们从哪个路由跳转过来 next 守卫可以通过next控制下一步的跳转
if (to.meta.auth) {
if (localStorage.getItem("user")) {
//放行,则跳转到消息页面
next();
} else {
//不放行,则通过路由/login 跳转到登陆页面
next({
path: '/login'
})
}
} else {
//放行
next() // next必须有,否则程序不会继续执行
}
})
new Vue({
el: '#app',
data: {
msg: ''
},
router, // 8、声明路由
methods: {
clear() { // 9、clear退出按钮的监听事件,用于注销用户,退出登陆
localStorage.removeItem("user"),
this.$router.push({ name: "index" })
}
}
})
</script>
</body>
</html>
当用户登陆之后就会跳转到/message路由,从而展示消息路由的组件,如果不是处于登陆状态,则跳转到/login路由。