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') //路由在實例化時跟普通的同樣