Vue路由router詳解
模塊化的方式使用路由插件
(1)安裝
npm install vue-router
(2)構建文件目錄
在src目錄下創建一個router文件夾,然後創建一個index.js
(3)這裡我們通過模塊化的方式進行創建路由,方便代碼的管理,這裡隻是對路插件進行瞭註冊,然後創建好路由對象。通過export default 關鍵字將創建好的路由對象暴露出去。
//index.js import VueRouter from 'vue-router' import Vue from 'vue' import Home from "../views/Home"; Vue.use(VueRouter)//註冊路由插件 export default new VueRouter({ routes:[{ path:'/', component:Home }] })
(4)在入口文件main.js引入創建好的路由對象,並且把他掛載到Vue實例中。
//main.js import Vue from 'vue' import App from './App.vue' import store from '@/store' import router from '@/router'//這裡就是引入瞭我們創建好的路由對象。模塊化的編程思維 Vue.config.productionTip = false Vue.prototype.bus = new Vue() new Vue({ store, router, render: h => h(App), }).$mount('#app')
使用路由
聲明式導航
可以理解成,通過標簽進行跳轉
聲明式導航:<router-link :to="...">
或者 <router-link to="...">
定義路由規則
{ path:'/', component:Home name:home }
(1)router-link導航標簽to屬性使用字符串方式
<router-link to="/">go to home</router-link>
(2)router-link導航標簽to使用對象的方式
使用路徑進行匹配
<router-link :to="{path:'/'}">go to home</router-link>
router-link導航標簽to屬性使用對象的方式並且使用路由名稱進行匹配
<router-link :to="{name:'home'}">go to home</router-link>
編程式導航
可以理解成JS進行跳轉
編程式導航:router.push(...)
下面的例子包含瞭動態路由匹配和query查詢參數的知識,不清楚的可以先看瞭這兩者的內容再回來看此處的內容。
// 字符串 router.push('home') // 對象 router.push({ path: 'home' }) // 命名的路由 router.push({ name: 'user', params: { userId: '123' }}) // 帶查詢參數,變成 /register?plan=private router.push({ path: 'register', query: { plan: 'private' }})
註意:如果提供瞭 path,params 會被忽略,上述例子中的 query 並不屬於這種情況。取而代之的是下面例子的做法,你需要提供路由的 name 與params配合或手寫完整的帶有參數的 path:
const userId = '123' router.push({ name: 'user', params: { userId }}) // -> /user/123 router.push({ path: `/user/${userId}` }) // -> /user/123 // 這裡的 params 不生效 router.push({ path: '/user', params: { userId }}) // -> /user
動態路由匹配
定義路由規則
{ path:'/user/:id', component:User name:user }
<router-link to="/user/01">go to home</router-link>
<router-link :to="{path:'/user/01'}">go to home</router-link>
<router-link :to="{name:'/user',params={id:'01'}}">go to home</router-link>
通過如上的方式進行定義,可以通過$route.params.id 獲動態路由參數:id值為’01‘
註意:
當使用對象的方式進行匹配時候,不能通過path和params的方式。隻能通過name和params的方式
如下方式,不能匹配到路由規則{path:’/user/:id’} ,如下表述隻能被理解成’/user’,
即使通過*通配符匹配到該路由,params也不會被傳遞過去,因為要有path這個屬性就不會去解析params的屬性瞭。
{ // 會匹配所有路徑 path: '*' } { // 會匹配以 `/user-` 開頭的任意路徑 path: '/user-*' }
通配符匹配路徑
我們通常使用*捕獲其他意外的路徑,進行個兜底的處理,通常將其導航到404錯誤頁面。
<router-link to=“/user?name=zhangsan">...</router-link> <router-link :to="{path:'/user?zhangsan'}">...</router-link> <router-link :to="{path:'/user',query:{name:'zhangsan'}}">...</router-link> <router-link :to="{name:'user',query:{name:'zhangsan'}}">...</router-link>
當使用一個通配符時,$route.params 內會自動添加一個名為 pathMatch 參數。它包含瞭 URL 通過通配符被匹配的部分
查詢參數query
<router-link to=“/user?name=zhangsan">...</router-link> <router-link :to="{path:'/user?zhangsan'}">...</router-link> <router-link :to="{path:'/user',query:{name:'zhangsan'}}">...</router-link> <router-link :to="{name:'user',query:{name:'zhangsan'}}">...</router-link>
查詢參數不想動態路由參數匹配那樣,就算使用瞭path,依然可以使用query進行傳參;
以上query傳遞過來的參數可以通過this.$route.query.name
進行獲取。
響應路由參數的變化
如果路由從/user/01
導航到/user/02
,原來的組件實例會被復用。因為有兩個路由都渲染同一個組件,這意味著組件的生命周期鉤子不會被再次調用。因此需要通過其他方式進行監聽參數的變化來做出響應。
(1)通過watch進行監聽
const User = { template: '...', watch: { $route(to, from) { // 對路由變化作出響應... } } }
(2)通過導航守衛進行監聽
const User = { template: '...', beforeRouteUpdate(to, from, next) { // react to route changes... // don't forget to call next() } }
命名路由,路由別名,重定向
特別地我把這三者的概念放在一起來闡述,是為瞭更好的去區分他們之間的區別。這些內容都是在路由規則去配置的。
{ path: '/pageOne', component:PageOne, alias:"/firstPage", name:"pageOne", redirect:{name:'pageTwo'} }, { path: '/pageTwo', component:PageTwo, name:'pageTwo' }
(1)命名路由:可以理解成給這個路由取個名字
即使通過name屬性給路由取一個名字
routes: [ { path: '/user/:userId', name: 'user', component: User } ]
(2)路由別名:可以理解成這個路由的第二個名字。
例如:/a的別名是/b,當用戶訪問/b的時候,URL會保持/b但是路由匹配到的內容則為/a,也就是知識URL內容顯示/b內容實則是/a
註意瞭:這裡別名要使用路徑的方式去表述,而不是跟命名路由那樣直接寫名字哦~
const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
(3)重定向:可以理解為訪問/a的時候直接跳轉到/b
重定向的表述有三種形式:
- 字符串
const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] })
- 對象
const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] })
- 方法
const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { // 方法接收 目標路由 作為參數 // return 重定向的 字符串路徑/路徑對象 }} ] })
嵌套路由
嵌套路由可以這麼理解,所匹配的路由渲染出來的組件中包含路由組件,’/user’當我們匹配到一個路由渲染出一個組件User,但是如果想繼續在User組件的<router-view ></router-view>繼續匹配。則我們要通過/user/childRouteName進一步匹配。”childRouteName”就是我們路由規則children中對應的path的值啦。
{ path: '/user', component: User, children: [ { // 當 /user//profile 匹配成功, // UserProfile 會被渲染在 User 的 <router-view> 中 path: 'profile', component: UserProfile }, { // 當 /user//posts 匹配成功 // UserPosts 會被渲染在 User 的 <router-view> 中 path: 'posts', component: UserPosts } ] }
APP.Vue中
<div id="app"> <router-view></router-view> </div>
User組件中
const User = { template: ` <div class="user"> <span>User組件</span> <router-view></router-view> </div> ` }
註意:
定義瞭嵌套路由,即定義瞭children的情況下,必須是完整的路由才可以匹配正確。也就是 當 /user/profile匹配成功,但是/user這樣是無法匹配成功的。
命名視圖
當一個組件上同時渲染多個視圖,註意是同級展示多個視圖,而不是嵌套展示。那此時就可以通過命名視圖來解決這個問題。
路由規則定義
{ path:"/namingRoute", components:{//註意此處components是帶's'結尾的,之前單個的時候是不帶的。 default:Home, one:PageOne, two:PageTwo } }
組件定義
<router-view></router-view>//渲染default對應的組件 <router-view name="one"></router-view>//渲染one對應的組件 <router-view name="two"></router-view>//渲染two對應的組件
當URL為:/namingRoute的時候 匹配到該路由,則會按照對應的router-view視圖組件進行渲染。
導航守衛
(1)全局守衛
可以理解成通過全局router實例對象router進行定義的守衛。
- route.beforeEach(全局前置守衛)
使用方式:
beforeEach((to,from,next)=>{ //... })
- router.beforeResolve(全局解析守衛)
在所有組件內守衛和異步路由組件被解析之後,解析守衛就被調用
使用方式:
router.beforeResolve((to, from, next) => { // ... })
- router.afterEach (全局後置鉤子)
鉤子不會接受 next 函數也不會改變導航本身:
使用方式:
router.afterEach((to, from) => { // ... })
使用的位置:通常在router文件夾下的index.js const router = new VueRouter({ ... }) //全局前置守衛 router.beforeEach((to, from, next) => { // ... }) //全局解析守衛 router.beforeResolve((to, from, next) => { // ... }) //全局後置鉤子 router.afterEach((to, from) => { // ... })
(2)路由獨享守衛
可以理解成在路由規則上定義的守衛
- beforeEnter
(3)組件內守衛
可以理解成在組件內定義的守衛
- beforeRouteEnter
還沒有創建組件實例,在該路由被confirm前調用。
const User = { template: `...`, beforeRouteEnter(to, from, next) { // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 因為當守衛執行前,組件實例還沒被創建 } }
註意:
該守衛不能直接使用this訪問vue實例對象,因為此時組件實例還沒有被創建。但是可以通過給next方法傳遞回調來方位組件的實例。
給next()傳遞回調,僅在beforeRouteEnter使用有效!!!
beforeRouteEnter (to, from, next) { next(vm => { // 通過 `vm` 訪問組件實例 }) }
- beforeRouteUpdate (2.2 新增)
在路由改變且該組件被服用時調用
const User = { template: `...`, beforeRouteUpdate(to, from, next) { // 在當前路由改變,但是該組件被復用時調用 // 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由於會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。 // 可以訪問組件實例 `this` } }
- beforeRouteLeave
在導航離開該組件對應的路由時調用
const User = { template: `...`, beforeRouteLeave(to, from, next) { // 導航離開該組件的對應路由時調用 // 可以訪問組件實例 `this` } }
導航解析的流程
正常首次訪問路由的執行順序
- beforeEach 全局的路由前置守衛
- beforeEnter 獨享路由守衛
- beforeRouteEnter 組件路由守衛
- beforeResolve 全局路由解析守衛
- afterEach 全局路由後置鉤子
- Dom渲染
- 調用beforeRouteEnter 組件路由守衛中傳遞給next的回調函數。並且把創建號的組件實例作為回調函數的參數傳入。
總結
本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!
推薦閱讀:
- vue的路由守衛和keep-alive後生命周期詳解
- 關於Vue Router的10條高級技巧總結
- Vue路由vue-router詳細講解指南
- Vue-router編程式導航的兩種實現代碼
- vue路由傳參方式的方式總結及獲取參數詳解