iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Modern Web

我的Vue學習筆記系列 第 21

Day21-路由守衛(Navigation Guards)

Navigation Guards有點像是生命週期的概念,變更路由前後時可以先執行一些動作,分別有「全域」、「路由」和「元件」三個Hook可以使用。

beforeEach(全域)

在路由被執行之前都會先經過這

const router = new VueRouter({ ... })
	router.beforeEach((to, from, next) => {
		//例如:身分驗證
		return await canUserAcess(to)
})
//canUserAcess(to)->false 路由的切換會禁止
//canUserAcess(to)->true/undefined 路由正常執行 

router.beforeEach的callback函式中

  • to 即將進入的路由
  • from 從何處進入的路由
  • next 繼續往下執行callback,沒有呼叫則路由中斷(Vue Router4開始可省略)
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated){ 
		next({ name: 'Login' })
	}
  else{ 
		next()
	}
})

//Vue Router4 後可以寫成
router.beforeEach((to) => {
  if (to.name !== 'Login' && !isAuthenticated){ 
		return({ name: 'Login' })
	}
})

beforeResolve(全域)

在路由跳轉前觸發,但晚於router.beforeEach,以及非同步路由元件解析後才被調用。

router.beforeResolve((to, from, next) => { 
	// do something... 
});

afterEach(全域)

跳轉後觸發,callback函式只有tofrom以及failure(表示路由轉跳失敗)。可以使用router.afterEach來搭配GA追蹤類的工具,來記錄使用者瀏覽紀錄:

router.afterEach((to, from, failure) => { 
	if (!failure) { 
		sendToAnalytics(to.fullPath); 
	} 
	else { 
		// fallback... 
	} 
});

beforeEnter(路由)

beforeEach作用一樣,但只能在route物件內註冊。可以依照routers規則選擇是否註冊,而beforeEach註冊後整個程式路由都會進入此hook中

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from) => {
        return false
      }
    }
  ]
})

元件內的Hook

  1. beforeRoutereEnter在路由尚未進入元件時被調用,callback有to,fromnext

    注意!! 在此處因為元件實體尚未建立,故拿不到this

    beforeRouteEnter (to, from, next) { 
    	// 沒有 this!!! 
    	next(vm => { 
    		// 可以透過 vm 指向元件實體 
    	}); 
    }
    
  2. beforeRouterUpdate路由被改變,但元件本身仍是同一個時被調用,例如/users/1換成/users/2路由更新但使用同一個元件。

    beforeRoutereEnter的callback相同,只差了next()

    // post.vue 
    export default { 
    	data() { 
    		return { 
    			post: null, 
    			error: null, 
    		} 
    	}, 
    	beforeRouteEnter(to, from, next) { 
    		// 因元件未建立,只能透過 next 來取得實體 
    		getPost(to.params.id, (err, post) => { 
    			next(vm => vm.setData(err, post)) 
    		}) 
    	}, 
    	async beforeRouteUpdate(to, from) { 
    		// 路由更新前,可使用this指向元件實體了! 
    		this.post = null; 
    		try { 
    			this.post = await getPost(to.params.id) 
    		} catch (error) { 
    			this.error = error.toString() 
    		} 
    	}, 
    }
    
  3. beforeRouterLeave路由離開元件時調用,參數有tofrom。通常用在詢問使用者是否要轉跳到另一個路由使用:

    beforeRouteLeave (to, from) {
      const answer = window.confirm('是否離開此頁?')
      if (answer) {
        return false
      }
    }
    

Navigation Guards執行順序

切換路由時,依序會進行:

  • beforeRouteLeave 離開目前路由 (元件)
  • beforeEach 開始進入新路由之前 (全域)
  • beforeEnter 開始進入新路由之前 (路由)
  • beforeRouteEnter 路由尚未進入該元件時 (元件)
  • beforeResolve 路由與所搭配的元件已被解析 (全域)
  • afterEach 當路由跳轉結束後 (全域)
  • beforeCreate 元件實體建立前 (Vue Hook)
  • created 元件實體已建立 (Vue Hook)
  • beforeMount 元件實體掛載前 (Vue Hook)
  • mounted 元件實體掛載完成 (Vue Hook)
  • beforeRouteEnter 內的 next() 回呼函式
  • beforeRouteUpdate 當路由更新時 (僅限同屬一個元件的情況,也可能完全不會發生)

參考資料

Router 進階應用 Day 10
https://ithelp.ithome.com.tw/articles/10214740
Navigation Guards
https://router.vuejs.org/guide/advanced/navigation-guards.html


上一篇
Day20-<router-link> 建立路由連結
下一篇
Day22-Vuex簡介
系列文
我的Vue學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言