前言
vue-router是什么:是vue.js官方的路由管理器和vue.js的核心深度的集成,讓開發者更加簡單的構建單頁面應用。
vue-router的功能是什么:嵌套的路由/視圖表
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 模塊化的、基于組件的路由配置
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 路由參數、查詢、通配符
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 基于vue.js過渡系統的視圖過渡效果
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 細粒度的導航控制(控制的很精細的意思,對很多細節也進行控制)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 帶有自動激活的 css class?鏈接
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?HTML5歷史模式或hash模式,在IE中自動降級
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?自定義滾動條行為
基礎
vue-router構建單頁面應用,只需要將組件映射到路由,熱后告訴vue-router在哪里渲染它們
簡單的例子:
使用vue-router有幾個方法
直接利用import引入router.js文件,在文件中寫組件的路由
利用編程式的導航
動態路由的匹配
有時候我們需要把某種模式匹配到的所有路由,全都映射到同個組件時,我們就會用到動態路由的匹配,路徑參數使用:標記當匹配到一個路由時,參數值會被設置到?this.$route.params,可以在每個組件內使用。
響應路由參數的變化
當使用路由參數時,原來的組件實例會被復用。因為兩個路由都渲染同個組件,比起銷毀再創建,復用則顯得更加高效,生命鉤子不被再次調用。復用組件時,想對路由參數的變化作出響應的話,可以用以下兩種方式
因為mounted ,created不會再調用?,?可以這兩種方式監聽參數變化,做相應的業務邏輯處理。
匹配優先級
匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高。
嵌套路由
要在嵌套的出口中渲染組件,需要在VueRouter的參數中使用children配置
注意:以/開頭的嵌套路徑會當作根路徑,充分使用嵌套組件而無須設置嵌套路徑,children?配置就是像?routes?配置一樣的路由配置數組,所以呢,你可以嵌套多層路由。
編程式導航
this.$router.push(location,onComplete?,onAbort?)
除了使用??創建 a 標簽來定義導航鏈接,我們還可以借助 router 的實例方法,通過編程式導航來實現:?this.$router.push({path:' '}} 。
這方法會向history棧添加一個新的記錄,所以,當用戶點擊瀏覽器后退按鈕時,則回到之前的地址
使用了path,params會被忽略,同樣的規則也適用于?router-link?組件的?to?屬性。
this.$router.replace (location,onComplete?,onAbort?)
和router.push很像唯一的不同是,它不會向history添加新紀錄,而是替換當前的history記錄
聲明式:<router-link :to="..."? replace>
編程式:router.replace(...)
router go(n)
n為整數,意思是在history記錄中向前或后退多少步,類似window.history.go(n)
命名路由
有時,在通過名稱來進行頁面路由跳轉會方便很多,可以在創建實例的時候給路由設置名稱
使用方法:
命名視圖
有時候想要同時(同級)展示多個視圖,而不是嵌套展示,這時候就可以使用命名視圖的方法,命名視圖首先需要在路由配置上命名組件是名字,使用<router-view?name=" "></router-view>來實現。
嵌套命名路由
重定向和別名
重定向(redirect)
別名(alias)
/a?的別名是?/b,則當用戶訪問?/b?時,URL 會保持為?/b,但是路由匹配為?/a,就像用戶訪問?/a?一樣。
“別名”的功能讓你可以自由地將 UI 結構映射到任意的 URL,不會受限于配置的嵌套路由結構。
路由組件傳參
使用$router會使其于路由高度耦合,從而使組件只能在特定的 URL 上使用
可以使用props對其組件和路由進行解耦
布爾模式
如果?props?被設置為?true,route.params?將會被設置為組件屬性。
對象模式
props?是一個對象,它會被按原樣設置為組件屬性,當?props?是靜態的時候有用。
函數模式
你可以創建一個函數返回?props。這樣你便可以將參數轉換成另一種類型,將靜態值與基于路由的值結合等。盡可能保持?props?函數為無狀態,因為它只會在路由發生變化時起作用。
HTML5 History 模式
vue-router?默認使用 hash 模式,使用 URL 的 hash 來模擬一個完整的 URL,當 URL 改變時,頁面不會重新加載。使用history模式時url會好看些(如:http://?dayou.com/user/id),完成 URL 跳轉而無須重新加載頁面。這種模式需要后臺配置支持,因為我們的應用是個單頁客戶端應用,如果后臺沒有正確的配置,當用戶在瀏覽器直接訪問?http://oursite.com/user/id?就會返回 404。服務端需要增加一個覆蓋所有情況的候選資源,如果 URL 匹配不到任何靜態資源,則應該返回同一個?index.html?頁面。
進階
導航守衛
vue-router?提供的導航守衛主要用來通過跳轉或取消的方式守衛導航,參數或查詢的改變并不會觸發進入/離開的導航守衛。可以觀察$router對象來應對這些變化用?beforeRouteUpdate?的組件內守衛,進入路由前先通過守衛,來判斷是否可以通過,進而到達頁面。
全局守衛
使用?router.beforeEach?注冊一個全局前置守衛,在定義router的地方定義
一個導航觸發時,全局前置守衛按照創建順序調用。守衛是異步解析執行,此時導航在所有守衛 resolve(解決) 完之前一直處于等待的狀態。
to: Route: 即將要進入的目標?路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來?resolve?這個鉤子。執行效果依賴?next?方法的調用參數。
next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是?confirmed?(確認的)。? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到?from?路由對應的地址。
next('/')?或者?next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向?next?傳遞任意位置對象,且允許設置諸如?replace: true、name: 'home'之類的選項以及任何用在?router-link?的?to?prop?或?router.push?中的選項。
next(error): (2.4.0+) 如果傳入?next?的參數是一個?Error?實例,則導航會被終止且該錯誤會被傳遞給?router.onError()?注冊過的回調。?
確保要調用?next?方法,否則鉤子就不會被 resolved。
全局解析守衛( router.beforeResolve )
和全局守衛區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。
全局后置鉤子
全局后置鉤子不接受next函數也不會改變導航本身
路由獨享守衛
在路由配置上直接定義?beforeEnter?守衛
組件內的守衛
路由組件內直接定義路由導航守衛:beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave
beforeRouteEnter( )不能獲取組件實例this,不過可以通過傳一個回調給?next來訪問組件實例。在導航被確認的時候執行回調,并且把組件實例作為回調方法的參數。
beforeRouteEnter?是支持next傳遞回調的唯一守衛。
對于?beforeRouteUpdate?和?beforeRouteLeave?來說,this?已經可用了,所以不支持傳遞回調
離開守衛通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過?next(false)?來取消
完整的導航解析流程
1、導航被觸發。
2、在失活的組件里調用離開守衛。
3、調用全局的?beforeEach?守衛。
4、在重用的組件里調用?beforeRouteUpdate?守衛 (2.2+)。
5、在路由配置里調用?beforeEnter。
6、解析異步路由組件。
7、在被激活的組件里調用?beforeRouteEnter。
8、調用全局的?beforeResolve?守衛 (2.5+)。
9、導航被確認。
10、調用全局的?afterEach?鉤子。
11、觸發 DOM 更新。
12、用創建好的實例調用?beforeRouteEnter?守衛中傳給?next?的回調函數。
路由元信息
定義路由的時可配置?meta?字段:
我們稱呼?routes?配置中的每個路由對象為?路由記錄。路由記錄可以是嵌套的,因此,當一個路由匹配成功后,可能匹配多個路由記錄
那么如何訪問這個?meta?字段呢
要確保最后使用了next( )
過渡效果
?是基本的動態組件,我們可以用組件給它添加過渡效果
單個路由的過渡效果
如果只想讓部分路由有過渡效果或者想路由的效果不同可在各路由組件內使用<transition>并且設置不同的name值
基于路由的動態過渡效果
基于當前路由與目標路由的變化關系,動態設置過渡效果
數據獲取
我們經常需要在頁面加載的時候獲取對應的數據,我們可以通過以下的兩種方式進行:
導航完成之后獲取:先完成導航,然后在接下來的組件生命周期鉤子中獲取數據。在數據獲取期間顯示“加載中”之類的指示。
導航完成之前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功后執行導航。
導航完成之后獲取
當你使用這種方式時,我們會馬上導航和渲染組件,然后在組件的?created?鉤子中獲取數據。這讓我們有機會在數據獲取期間展示一個 loading 狀態,還可以在不同視圖間展示不同的 loading 狀態。
導航完成之前獲取
這種方式我們在導航轉入新的路由前獲取數據。我們可以在接下來的組件的?beforeRouteEnter?守衛中獲取數據,當數據獲取成功后只調用?next?方法。
滾動行為
當切換到新路由時,想要頁面滾到頂部,或是保持原先的滾動位置,就像重新加載頁面那樣。
當創建一個 Router 實例,你可以提供一個?scrollBehavior?方法:
異步滾動
如果在不知道要滾動到那個具體位置,則可以使用異步滾動,獲取后臺要滾動到的具體位置,返回一個 Promise 來得出預期的位置描述:
將其掛載到從頁面級別的過渡組件的事件上,令其滾動行為和頁面過渡一起良好運行是可能的
路由懶加載
當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。
所以我們把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了。
結合 Vue 的異步組件和 Webpack 的代碼分割功能,輕松實現路由組件的懶加載。
首先,可以將異步組件定義為返回一個 Promise 的工廠函數 (該函數返回的 Promise 應該 resolve 組件本身):
const Foo = () => Promise.resolve({ /* 組件定義對象 */ })
第二,在 Webpack 2 中,我們可以使用動態 import語法來定義代碼分塊點 (split point):
import('./Foo.vue') // 返回 Promise
定義一個能夠被 Webpack 自動代碼分割的異步組件
const Foo = () => import('./Foo.vue')
把組件按組分塊
有時候我們想把某個路由下的所有組件都打包在同個異步塊 (chunk) 中
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
Webpack 會將任何一個異步模塊與相同的塊名稱組合到相同的異步塊中。