Vue Router
如何使用Vue Router,這是Vue應用程式中必不可少的一部分之一
簡介
在JavaScript網頁應用程式中,路由器是將目前顯示的視圖與瀏覽器地址欄內容同步的部分。
換句話說,它是當你在頁面上點擊某個元素時,使URL改變並顯示正確視圖的部分。
傳統上,網頁是基於URL構建的。當你訪問特定的URL時,會顯示特定的頁面。
隨著在瀏覽器內運行並改變使用者所見的應用程式的引入,許多應用程式打破了這種交互方式,你必須手動使用瀏覽器的History API更新URL。
當你需要將URL與應用程式中的視圖同步時,你就需要一個路由器。這是一個非常常見的需求,現代的主要框架現在都允許你進行路由管理。
Vue Router庫是Vue.js應用程式開發時的首選。Vue並不強制使用這個庫。你可以使用任何通用的路由庫,或者自己創建和History API集成,但是使用Vue Router的好處是它是官方的。
這意味著它是由維護Vue的同一群人維護的,所以你可以在框架中得到更一致的整合,並且保證它將始終與未來的版本兼容,無論是什麼版本。
安裝
Vue Router可以通過npm的vue-router
包來獲取。
如果你使用script
標籤引入Vue,可以使用以下方式引入Vue Router。
1 | <script src="https://unpkg.com/vue-router"></script> |
unpkg.com是一個非常方便的工具,可以通過一個簡單的鏈接在瀏覽器中提供每個npm包
如果你使用Vue CLI,可以使用以下方式安裝
1 | npm install vue-router |
一旦你安裝了vue-router
並使其可用,可以在你的應用程序中導入它。
你需要在vue
之後導入它,並調用Vue.use(VueRouter)
將其安裝在應用程序中。
1 | import Vue from 'vue' |
在調用Vue.use()
並傳遞路由器對象之後,在應用程式的任何組件中都可以訪問這些對象:
this.$router
是路由器對象this.$route
是當前路由對象
路由器對象
當在將Vue Router安裝到根Vue組件時,可以使用this.$router
從任何組件中訪問路由器對象,它提供了許多不錯的功能。
我們可以使用以下方法導航至新路由:
this.$router.push()
this.$router.replace()
this.$router.go()
這類似於History API的pushState
,replaceState
和go
方法。
push()
用於切換到新的路由,將新項目添加到瀏覽器的歷史記錄中。replace()
類似,只是它不會將新狀態推送到歷史記錄中。
使用示例:
1 | this.$router.push('about') //命名路由,稍後查看 |
go()
可以前進和後退,接受一個可能為正或負的數字來倒退或前進歷史記錄:
1 | this.$router.go(-1) //後退1步 |
定義路由
在這個例子中,我使用了一個Vue單文件組件。
在模板中,我使用一個nav
標籤,其中包含3個router-link
組件,這些組件通過to
屬性分配一個標籤(Home/Login/About)和一個URL。
router-view
組件是Vue Router將匹配當前URL的內容放入其中的地方。
1 | <template> |
一個router-link
組件默認渲染為一個a
標籤(你可以更改它)。每次路由發生更改,無論是通過點擊鏈接還是更改URL時,都會向與活動路由相關聯的元素添加一個router-link-active
類,使您能夠對其進行樣式設置。
在JavaScript部分,我們首先包含並安裝了路由器,然後定義了3個路由组件。
我們將它們傳遞給router
對象的初始化,然後將此對象傳遞給Vue根實例。
代碼如下:
1 | <script> |
通常,在Vue應用程式中,您使用以下方式實例化並安裝根應用程式:
1 | new Vue({ |
當使用Vue Router時,您不需要傳遞render
屬性,而是使用router
。
上面的示例中使用的語法:
1 | new Vue({ |
是以下方式的縮寫:
1 | new Vue({ |
在上面的示例中,我們將routes
數組傳遞給了VueRouter
構造函數。該數組中的每個路由都具有path
和component
參數。
如果您還傳遞一個name
參數,則是一個命名路由。
使用命名路由來將參數傳遞給路由的push和replace方法
還記得我們以前如何使用路由器對象來推送新狀態的嗎?
1 | this.$router.push({ path: 'about' }) |
使用命名路由,我們可以將參數傳遞給新路由:
1 | this.$router.push({ name: 'post', params: { post_slug: 'hello-world' } }) |
對於replace()
也是一樣的:
1 | this.$router.replace({ name: 'post', params: { post_slug: 'hello-world' } }) |
當用戶點擊了router-link
時會發生什麼
應用程式會渲染與鏈接所傳遞的URL相匹配的路由組件。
處理URL的新路由組件將被實例化並調用其guards,舊的路由組件將被摧毀。
路由保護
既然我們提到了guards,讓我們來介紹一下。
你可以將它們看作生命週期鉤子或中間件,它們是在應用程式執行期間的特定時間點調用的函數。你可以介入並修改路由的執行,重定向或取消請求。
通過在路由器的beforeEach()
和afterEach()
屬性中添加回調函數,你可以擁有全局的路由保護。
beforeEach()
在導航確認之前調用beforeResolve()
在執行beforeEach並調用所有組件的beforeRouterEnter
和beforeRouteUpdate
保護之後,但在導航確認之前。如果您想要進行最終檢查afterEach()
在導航確認後調用
“導航確認”是什麼意思?我們稍後會看到。在此之前,將其視為“應用程式可以轉到該路由”。
使用方法如下:
1 | this.$router.beforeEach((to, from, next) => { |
1 | this.$router.afterEach((to, from) => { |
to
和from
代表我們要前往和從哪裡來的路由對象。beforeEach
還有一個額外的參數next
,如果我們以false
調用它,將會阻止導航,並導致它未確認。就像在Node中間件中一樣,如果你熟悉的話,應該總是調用next(),否則執行將被阻塞。
單個路由組件也有guards:
beforeRouteEnter(from, to, next)
在當前路由確認之前調用beforeRouteUpdate(from, to, next)
在路由更改但仍使用該組件(對於動態路由,請參見下文)的情況下調用beforeRouteLeave(from, to, next)
在我們從當前路由移開時調用
我們之前提到過導航。要確定是否確認到某個路由,Vue Router執行了一些檢查:
- 它在當前組件中調用
beforeRouteLeave
保護 - 它調用路由器的
beforeEach()
保護 - 它在任何需要重複使用的組件中,調用
beforeRouteUpdate()
,如果有的話 - 它在路由對象上調用
beforeEnter()
保護(我沒有提到,但你可以在這裡找到它) - 它在應該進入的組件中調用
beforeRouterEnter()
保護 - 它在路由器的
beforeResolve()
保護中調用 - 如果一切順利,導航確認!
- 它調用路由器的
afterEach()
保護
您可以使用特定於路由的保護(beforeRouteEnter
和beforeRouteUpdate
,在動態路由的情況下)作為生命週期鉤子使用,因此您可以開始進行數據提取請求,例如。
動態路由
上面的示例根據URL顯示不同的視圖,處理/
、/login
和/about
路徑。
非常常見的需求是處理動態路由,比如在/post/
下有所有帖子,每個帖子都有一個別名:
/post/first
/post/another-post
/post/hello-world
您可以使用動態片段來實現這一點。
上面的示例是使用靜態片段的:
1 | const router = new VueRouter({ |
我們增加了一個動態片段來處理部落格帖子:
1 | const router = new VueRouter({ |
注意:post_slug
語法。這表示您可以使用任何字符串,並將其映射到post_slug
佔位符。
您不僅限於這種類型的語法。Vue依賴於此庫來解析動態路由,您可以使用Regular Expressions實現更多功能。
現在,在Post路由組件中,我們可以使用$route
引用路由,並使用$route.params.post_slug
引用帖子別名。
1 | const Post = { |
我們可以使用此參數從後端加載內容。
您可以有多個動態片段,它們在同一個URL中:
/post/:author/:post_slug
還記得我們在以前談到用戶瀏覽到新路由時會發生什麼嗎?
對於動態路由的情況,情況是有些不同的。
為了更高效,Vue並不銷毀當前的路由組件並重新實例化它,而是重用當前的實例。
當發生這種情況時,Vue會調用beforeRouteUpdate
生命周期事件。在那裡,您可以執行任何需要的操作:
1 | const Post = { |
使用props
在示例中,我使用$route.params.*
來訪問路由數據。一個組件不應與路由器緊密耦合,相反,我們可以使用props:
1 | const Post = { |
注意將props: true
傳遞給路由對象以啟用此功能。
嵌套路由
我之前提到您可以在同一個URL中有尽可能多的動態片段,比如:
/post/:author/:post_slug
因此,假設我們有一個負責第一個動態片段的Author組件:
1 | <template> |
我們可以在Author模板中插入第二個router-view
組件實例:
1 | const Author = { |
我們增加Post組件:
1 | const Post = { |
然後我們將內部動態路由注入VueRouter配置中:
1 | const router = new VueRouter({ |
tags: [“Vue”, “Vue Router”, “JavaScript”, “web development”, “frontend”]