VueJs(12)---vue-router(导航守卫,路由元信息)
vue-router(导航守卫,路由元信息,获取数据)
之前泄露两篇有关vue-router博客:
一、导航守卫
当做Vue-cli项目的时候感觉在路由跳转前做一些验证,比如登录验证,是网站中的普遍需求,这个时候就需要导航守卫,你可以在页面跳转前做逻辑判断,时候跳转,跳转到指定页面。
(1)全局的(beforeEach,afterEach,beforeResolve),
(2)单个路由独享的(beforeEnter),
(3)组件级的(beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave)。
1、全局守卫
你可以使用 router.beforeEach
注册一个全局前置守卫:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => {
// 业务逻辑处
})
每个守卫方法接收三个参数:
to: Route
: 即将要进入的目标 路由对象from: Route
: 当前导航正要离开的路由next: Function
: 一定要调用该方法来 resolve 这个钩子。执行效果依赖next
方法的调用参数。
next()
: 进行管道中的下一个钩子。这个是必须要的,否在无法完成跳转。
next(false)
: 中断当前的导航。就相当于点击之后不会跳转到指定页面,就相当于没有写next()一样。
next('/')
或者 next({ path: '/' })
: 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next
传递任意位置对象,
next(error)
: (2.4.0+) 如果传入 next
的参数是一个 Error
实例,则导航会被终止且该错误会被传递给 router.onError()
注册过的回调。
全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next
函数也不会改变导航本身
router.afterEach((to, from) => {
// ...
})
路由独享的守卫
你可以在路由配置上直接定义 beforeEnter
守卫
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
2、组件内的守卫
最后,你可以在路由组件内直接定义以下路由导航守卫
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
}
}
beforeRouteEnter
守卫 不能 访问 this
,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
注意 beforeRouteEnter
是支持给 next
传递回调的唯一守卫。对于 beforeRouteUpdate
和 beforeRouteLeave
来说,this
已经可用了,所以不支持传递回调,因为没有必要了。
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false)
来取消。
beforeRouteLeave (to, from , next) {
const answer = window.confirm('你确定要退出吗')
if (answer) {
next()
} else {
next(false)
}
}
下面用一个小案例说明:
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app">
<button type="button" @click="fooClick">/user/foo</button>
<button type="button" @click="profileClick">/user/foo/profile</button>
<button type="button" @click="postsClick">/user/foo/posts</button> <router-view></router-view>
</div>
<script>
//定义了三个组件
const UserHome = { template: '<div>Home</div>'}
const UserProfile = {template: '<div>Profile</div>' }
const UserPosts = {template: '<div>Posts</div>'} //匹配了三个路由
const router = new VueRouter({
routes: [{
path: '/user/foo',
component: UserHome,
beforeEnter: (to, from, next) => {
console.log('进入UserHome组件');
next();
}
}, {
path: '/user/foo/profile',
component: UserProfile,
beforeEnter: (to, from, next) => {
console.log('进入profile组件');
next();
}
}, {
path: '/user/foo/posts',
component: UserPosts,
beforeEnter: (to, from, next) => {
console.log('UserPosts组件');
//这里设置flase说明就算路径为'/user/foo/posts',也不会进入UserPosts组件
next(false);
}
}]
})
//设置全局导航守卫
router.beforeEach((to, from, next) => {
console.log('进入全局守卫导航');
console.log('进入路由路径:' + to.path);
console.log('离开路由路径:' + from.path);
next();
})
const app = new Vue({
el: '#app',
router,
data: {
foo: '/user/foo',
profile: '/user/foo/profile',
posts: '/user/foo/posts'
},
methods: {
fooClick: function(event) {
this.$router.push({
path: this.foo
});
},
profileClick: function(event) {
this.$router.push({
path: this.profile
});
},
postsClick: function(event) {
this.$router.push({
path: this.posts
});
} }
})
</Script>
效果:
通过上面可以得出以下结论:
1、全局守卫会比组件守卫先执行
2.全局守卫第一次加载页面to和from路径都是“/”
3.每一次路径改变都会调用全局组件,路径不变是不会调用全局守卫,也不会在调用组件守卫
4.我在/user/foo/posts路径设置为next(flase)是,当点击它是并没有跳转UserPosts组件,页面显示的还是profile说明跳转失败。
二、路由元信息(meta)
为什么会有路由元信息这个东西?首先要知道它到底有什么作用。
我们在做网站登录验证的时候,可以使用到beforeEach 钩子函数进行验证操作,如下面代码 ,如果页面path为’/goodsList’,那么就让它跳转到登录页面,实现了验证登录。
router.beforeEach((to, from, next) => {
if (to.path === '/goodsList') {
next('/login')
} else
next()
})
如果需要登录验证的网页多了怎么办?
1.这里是对比path。如果需要验证的网页很多,那么在if条件里得写下所有的路由地址,将会是非常麻烦的一件事情。
2.因为路由是可以嵌套的。有’/goodsList’,那么可能会有’/goodsList/online’,再或者还有’/goodsList/offline’、’/goodsList/audit’、’/goodsList/online/edit’等等。
如果像刚才例子中这样对比(to.path === ‘/goodsList’),就非常单一,其他的路径压根不会限制(验证)到,照样能正常登陆!因为每个to.path根本不一样。
我们所理想的就是把’/goodsList’限制了,其他所有的以’/goodsList’开头的那些页面都给限制到!
to Route: 即将要进入的目标 路由对象
我们打印一下to
它有很多属性,有
- fullPath
- hash
- matched
- meta
- name
- params
- path
- query
其中有个属性,matched,就是匹配了的路由,我们打印出来,这个是个数组。它的第一项就是{path: “/goodslist”},一直到最为具体的当前path (例如:{path: “/goodslist/online/edit”})
这里可以循环matched这个数组,看每一项的path 有没有等于’/goodsList’,只要其中一个有,那么就让它跳转到登录状态
router.beforeEach((to, from, next) => {
if (to.matched.some(function (item) {
return item.path == '/goodslist'
})) {
next('/login')
} else
next()
})
那么这里只是对goodsList进行验证判断,且限制的还是path,就相当于把goodsList下面都给限制了,但有些东西是不需要登陆直接可以显示在页面的,比如:资讯信息,广告信息。这么做不就不可行了。用path来做限制似乎有点不好用。轮到主角登场了
meta字段(元数据)
直接在路由配置的时候,给每个路由添加一个自定义的meta对象,在meta对象中可以设置一些状态,来进行一些操作。用它来做登录校验再合适不过了
{
path: '/actile',
name: 'Actile',
component: Actile,
meta: {
login_require: false
},
},
{
path: '/goodslist',
name: 'goodslist',
component: Goodslist,
meta: {
login_require: true
},
children:[
{
path: 'online',
component: GoodslistOnline
}
]
}
这里我们只需要判断item下面的meta对象中的login_require是不是true,就可以做一些限制了
router.beforeEach((to, from, next) => {
if (to.matched.some(function (item) {
return item.meta.login_require
})) {
next('/login')
} else
next()
})
meta还可以放其它信息,比如可以存储该路由相关信息(例如:设置每个路由的title,取路由的title设置为选项卡的标题)
{
path: '/router2',
name: 'router2',
component:router2,
meta:{
title:"积分模块"
}
}
// 全局前置守卫
router.beforeEach((to,from,next) => {
console.log(to);
console.log(from);
if(to.meta.title) {
document.title = to.meta.title;
} else {
document.title = '我是默认的title'
}
next();
});
三、获取数据
有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。
我们可以通过两种方式来实现:
(1)导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示。
(2)导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。
1、导航完成后获取数据
当你使用这种方式时,我们会马上导航和渲染组件,然后在组件的 created
钩子中获取数据。这让我们有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。
假设我们有一个 Post
组件,需要基于 $route.params.id
获取文章数据:
<template>
<div class="post">
<div class="loading" v-if="loading">
Loading...
</div> <div v-if="error" class="error">
{{ error }}
</div> <div v-if="post" class="content">
<h2>{{ post.title }}</h2>
<p>{{ post.body }}</p>
</div>
</div>
</template>
export default {
data () {
return {
loading: false,
post: null,
error: null
}
},
created () {
// 组件创建完后获取数据,
// 此时 data 已经被 observed 了
this.fetchData()
},
watch: {
// 如果路由有变化,会再次执行该方法
'$route': 'fetchData'
},
methods: {
fetchData () {
this.error = this.post = null
this.loading = true
// replace getPost with your data fetching util / API wrapper
getPost(this.$route.params.id, (err, post) => {
this.loading = false
if (err) {
this.error = err.toString()
} else {
this.post = post
}
})
}
}
}
(err, post) =>是ES6写法,意思大概就是function(err, post){}大括号就相当于方法类逻辑。
2、在导航完成前获取数据
通过这种方式,我们在导航转入新的路由前获取数据。我们可以在接下来的组件的 beforeRouteEnter
守卫中获取数据,当数据获取成功后只调用 next
方法。
export default {
data () {
return {
post: null,
error: null
}
},
beforeRouteEnter (to, from, next) {
getPost(to.params.id, (err, post) => {
next(vm => vm.setData(err, post))
})
},
// 路由改变前,组件就已经渲染完了
// 逻辑稍稍不同
beforeRouteUpdate (to, from, next) {
this.post = null
getPost(to.params.id, (err, post) => {
this.setData(err, post)
next()
})
},
methods: {
setData (err, post) {
if (err) {
this.error = err.toString()
} else {
this.post = post
}
}
}
}
在为后面的视图获取数据时,用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的指示。如果数据获取失败,同样有必要展示一些全局的错误提醒。
想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。上尉【1】
VueJs(12)---vue-router(导航守卫,路由元信息)的更多相关文章
- router.beforeEach、路由元信息、导航守卫与函数式编程
一.函数的识别: 1.router.beforeEach:主函数.高阶函数.入口函数: 2.匿名参量函数:处理跳转过程中的附加逻辑 (to, from, next) => { if (to.ma ...
- vue router 导航守卫生命周期
导航守卫 导航守卫主要用来通过跳转或取消的方式守卫导航.有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的.(记住参数或查询的改变并不会触发进入/离开的导航守卫.你可以通过观察$r ...
- vue进阶:vue-router之导航守卫、路由元信息、路由懒加载
1.导航被触发 2.在失活的组件里调用离开守卫:beforeRouteLeave —— 组件内守卫(离开组件). 3.调用全局的beforeEach守卫 —— 全局守卫(进入组件). 4.在重用组件里 ...
- vue-router路由元信息详解
一.官方文档 路由元信息:定义路由的时候可以配置 meta 字段 const router = new VueRouter({ routes: [ { path: '/foo', component: ...
- vue-router路由元信息及keep-alive组件级缓存
路由元信息?(黑人问号脸???)是不是这么官方的解释很多人都会一脸懵?那么我们说meta,是不是很多人恍然大悟,因为在项目中用到或者看到过呢? 是的,路由元信息就是我们定义路由时配置的meta字段:那 ...
- vue-router之路由元信息
路由元信息?(黑人问号脸???)是不是这么官方的解释很多人都会一脸懵?那么我们说meta,是不是很多人恍然大悟,因为在项目中用到或者看到过呢? 是的,路由元信息就是我们定义路由时配置的meta字段:那 ...
- vue-router 路由元信息 终于搞明白了路由元信息是个啥了
vue-router 路由元信息:https://blog.csdn.net/wenyun_kang/article/details/70987840 终于搞明白了路由元信息是个啥了:https:// ...
- vue 路由元信息
官方文档:路由meta元信息 前言: 在设置面包屑导航还有菜单栏的时候,路由的meta字段可以自定义我们需要的信息,然后路由跳转的时候,提供我们判断条件 文档: 定义路由的时候可以配置 meta 字段 ...
- vue.js利用vue.router创建前端路由
node.js方式: 利用node.js安装vue-router模块 cnpm install vue-router 安装完成后我们引入这个模板! 下载vue-router利用script引入方式: ...
随机推荐
- 有关uploadifive的使用经验(转:http://www.cnblogs.com/itBscs/p/4781786.html )
这段时间做了一个项目用到uploadifive上传控件,和uploadify不同,这个控件是基于HTML5的版本而不用支持falsh,因而移动端也可以使用. 整理用过的相关属性与方法: 属性 作 ...
- ROS(indigo)机器人操作系统学习资料和常用功能包汇总整理(ubuntu14.04LTS)
ROS(indigo)机器人操作系统学习资料和常用功能包汇总整理(ubuntu14.04LTS) 1. 网站资源: ROSwiki官网:http://wiki.ros.org/cn GitHub ...
- Mysql中limit的用法详解
Mysql中limit的用法详解 在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,为我们提供了limit这样一个功能. SELECT * FROM table LIMIT [offset ...
- 【leetcode75】Intersection of Two Arrays(数组的交集)
题目描述: 给定两个数组求他们的公共部分,输出形式是数组,相同的元素只是输出一次 例如: nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2]. 原文描述: ...
- Zookeeper实现负载均衡
原理解析 架构图 每台WorkServer启动的时候都会到Server创建临时节点. 每台ClientServer启动的时候,都会到S ...
- matlab学习日志之并行运算
原文地址:matlab并行计算,大家共同学习吧,涉及到大规模数据量处理的时候还是效果很好的 今天搞了一下matlab的并行计算,效果好的出乎我的意料. 本来CPU就是双核,不过以前一直注重算法,没注意 ...
- android放大镜效果实现
概述 我相信很多用过英语应用的同学都看多一个放大镜的效果,就是选中一段文字后,会有一个放大镜,这个究竟怎么实现的呢,我们今天来分析分析. 源码分析 public class ShaderView ex ...
- hadoop上的C++程序开发
hadoop可以用C++开发,命令运行方式为pipes,例子:hadoop pipes -conf job_config.xml -input input/myfile.txt -output out ...
- (NO.00001)iOS游戏SpeedBoy Lite成形记(一)
这是本猫第一个原创iOS游戏,留此为证!看编号貌似要写9万多个,千锤百炼还是太少吧!? ;) 这是一个赛跑游戏,几位选手从起点跑到终点看谁用的时间最少.现在需要实现的功能是: 1.8位选手从起点移动至 ...
- 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示
去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...