1、导航守卫
完整的导航解析流程:vue
参数或查询的改变并不会触发进入/离开的导航守卫。能够经过观察$route对象来应对这些变化,或使用beforeRouteUpdate的组件内守卫。
一、全局前置守卫
router.beforeEachwebpack
const router = new VueRouter({...}) router.beforeEach(to,from,next) => { /*to:Route--即将要进入的目标路由对象*/ /*from:Route--当前导航正要离开的路由*/ /*next:function--必需要调用该方法来resolve这个钩子。执行效果依赖next方法的调用参数。*/ next() /*进行管道中的下一个钩子,若所有执行完了,则导航的状态就是confirmed。*/ next(false) /*中断当前的导航。若是浏览器的url改变了(多是用户手动或浏览器后退),那么url会重置到from路由对应的地址。*/ next('/') /*同下*/ next({path:'/'}) /*跳转到一个不一样的地址。*/ next(error) /*导航被终止,且错误会传递给router.onError()注册过的回调。*/ }
确保next函数在任何给定的导航守卫中都被严格调用一次。可出现多于一次,但只能在全部的逻辑路径都不重叠的状况下,不然钩子永远都不会被解析或报错。web
/* BAD */ router.beforeEach((to, from, next) => { if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' }) /*若是用户未能验证身份,则 `next` 会被调用两次*/ next() }) /* GOOD */ router.beforeEach((to, from, next) => { if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' }) else next() })
二、全局解析守卫
router.beforeResolve--与router.beforeEachj相似,区别为:在导航被确认以前,同时在全部组件内守卫和异步路由组件被解析以后,解析守卫就被调用。
三、全局后置钩子
router.afterEach()--无next(),也不会改变导航自己vuex
router.afterEach(to,from)=>{ //... }
路由配置方式:
一、路由独享的守卫--直接在路由配置上定义beforeEnter守卫promise
const router = new VueRouter({ routes: [ { path: '/user', component: User, beforeEnter: (to,from,next)=>{} } ] })
二、组件内的守卫
能够在路由组件内直接定义如下路由导航守卫
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave浏览器
const Foo = { template: `...`, beforeRouteEnter(to, from, next) { /* 在渲染该组件的对应路由被 confirm 前调用*/ /*不能!获取组件实例 `this`*/ /*由于当守卫执行前,组件实例还没被建立,能够经过传一个回调给next来访问组件实例,仅该守卫支持此方法*/ next(vm => { /*经过vm访问组件实例*/ }) }, beforeRouteUpdate(to, from, next) { /* 在当前路由改变,可是该组件被复用时调用*/ /* 举例来讲,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候*/ /* 因为会渲染一样的 Foo 组件,所以组件实例会被复用。而这个钩子就会在这个状况下被调用。*/ /* 能够访问组件实例 `this`*/ this.name = to.params.name next() }, beforeRouteLeave(to, from, next) { /* 导航离开该组件的对应路由时调用*/ /* 能够访问组件实例 `this`*/ /*该守卫能够用来禁止用户在还未保存修改前忽然离开,导航能够经过next(false)取消*/ const answer = window.confirm('尚未保存,肯定要离开吗') if(answer){ next() }else{ next(false) } } }
2、路由元信息-meta服务器
路由登陆拦截异步
/*一、在须要作登陆验证的路由中设置meta*/ requireAuth值为true const router = new VueRouter({ routes = [ { path: '/detail', name: 'detail', component: Detail, meta: { requireAuth: true } }, { path: '/login', name: 'login', component: Login } ] }) /*二、router.beforeEach()钩子函数,会在进入每一个网页以前被调用,可在该钩子函数内作路由拦截*/ router.beforeEach((to,from,next) => { /*判断将进入的路由是否须要路由拦截*/ if(to.matched.some(record => record.meta.requireAuth){ /*vuex.state判断token是否存在*/ if(store.state.token){ /*已登陆*/ next() }else{ next({ path: '/login', query: {redirect: to.fullPath} }) } } else { next() } })
3、过渡动效
使用<transition>标签将<router-view>标签包裹能够添加一些过渡效果,会给在这个router-view中的路由都加上同一种效果。
若想给不一样的路由加不一样的效果,能够在路由组件中设置<transition>添加效果ide
const Foo = { template: ` <transition name="slide"> <div class="foo">...</div> </transition> ` } const Bar = { template: ` <transition name="fade"> <div class="bar">...</div> </transition> ` }
设置动态过渡函数
<!-- 使用动态的 transition name --> <transition :name="transitionName"> <router-view></router-view> </transition> //... // 接着在父组件内 // watch $route 决定使用哪一种过渡 watch: { '$route' (to, from) { const toDepth = to.path.split('/').length const fromDepth = from.path.split('/').length this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' } }
4、数据获取
在进入某个路由后,须要从服务器获取数据,有两种方式:
一、导航完成以后获取:
在路由组件的created钩子函数中调用获取数据的方法
export default{ data (){ return { loading: false } }, created(){ //组件建立完成后获取数据,此时data已经被observed了 this.fetchData() }, methods: { fetchData() { this.loading = true //发起数据请求,此时能够经过$route.params获取url上的数据 getPost(this.$route.params.id,(res)=>{ //... }) } } }
二、在导航前获取数据
在要跳转的路由组件中的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 } } } }
5、滚动行为
当切换到新路由时,页面滚动到顶部或保持原先的滚动位置,能够在router实例中提供一个scrollBehavior方法。
const router = new VueRouter({ routes: [...], scrollBehavior(to,from,savedPosition){ //return 指望滚动到的位置 //return {x: number, y: number} //滚动到顶部 //return {x:0,y:0} //savedPosition在按下后退和前进按钮时可用 if(savedPosition) { return savedPosition } else { return {x:0,y:0} } } })
模拟滚动到锚点
scrollBehavior(to,from,savedPosition){ if(to.hash) { return { selector: to.hash, //设置平滑滚动 behavior: 'smooth' } } }
6、路由懒加载
为提升加载效率,使用懒加载,让路由被访问时才加载对应组件。需结合Vue异步组件和webpack
//一、将异步组件定义为返回一个promise的工厂函数。 const Foo = ()=>{ Promise.resolve({ //组件定义对象 }) } //二、使用import引入组件 import('./Foo.vue') //import返回一个promise //可结合二者 const Foo = ()=> import('./Foo.vue') //路由在实例化时跟普通的同样