https://unpkg.com/vue-router/...html
Unpkg.com 提供了基於 NPM 的 CDN 連接。上面的連接會一直指向在 NPM 發佈的最新版本。你也能夠像 https://unpkg.com/vue-router@... 這樣指定 版本號 或者 Tag。vue
在 Vue 後面加載 vue-router,它會自動安裝的:vue-router
<script src="/path/to/vue.js"></script> <script src="/path/to/vue-router.js"></script>
npm install vue-router
若是在一個模塊化工程中使用它,必需要經過 Vue.use() 明確地安裝路由功能:npm
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter)
若是使用全局的 script 標籤,則無須如此(手動安裝)。編程
教程中的案例代碼將使用 ES2015 來編寫。瀏覽器
用 Vue.js + vue-router 建立單頁應用,是很是簡單的。使用 Vue.js ,咱們已經能夠經過組合組件來組成應用程序,當你要把 vue-router 添加進來,咱們須要作的是,將組件(components)映射到路由(routes),而後告訴 vue-router 在哪裏渲染它們。app
1建立組件:建立單頁面應用須要渲染的組件 2建立路由:建立VueRouter實例 3映射路由:調用VueRouter實例的map方法 4啓動路由:調用VueRouter實例的start方法
使用v-link指令 使用<router-view>標籤
應用在首次運行時右側是一片空白,應用一般都會有一個首頁,例如:Home頁。
使用router.redirect方法將根路徑重定向到/home路徑:ide
router.redirect({ '/': '/home' })
router.redirect方法用於爲路由器定義全局的重定向規則,全局的重定向會在匹配當前路徑以前執行。模塊化
咱們常常須要把某種模式匹配到的全部路由,全都映射到同個組件。例如,咱們有一個 User 組件,對於全部 ID 各不相同的用戶,都要使用這個組件來渲染。那麼,咱們能夠在 vue-router 的路由路徑中使用『動態路徑參數』(dynamic segment)來達到這個效果:佈局
const User = { template: '<div>User</div>' } const router = new VueRouter({ routes: [ // 動態路徑參數 以冒號開頭 { path: '/user/:id', component: User } ] })
如今呢,像 /user/foo 和 /user/bar 都將映射到相同的路由。
一個『路徑參數』使用冒號 : 標記。當匹配到一個路由時,參數值會被設置到 this.$route.params,能夠在每一個組件內使用。因而,咱們能夠更新 User 的模板,輸出當前用戶的 ID:
const User = { template: '<div>User {{ $route.params.id }}</div>' }
你能夠在一個路由中設置多段『路徑參數』,對應的值都會設置到 $route.params 中。例如:
模式 | 匹配路徑 | $route.params | |
---|---|---|---|
/user/:username | /user/evan | { username: 'evan' } | |
/user/:username/post/:post_id | /user/evan/post/123 | { username: 'evan', post_id: 123 } |
除了 $route.params 外,$route 對象還提供了其它有用的信息,例如,$route.query(若是 URL 中有查詢參數)、$route.hash 等等。你能夠查看 API 文檔 的詳細說明。
提醒一下,當使用路由參數時,例如從 /user/foo 導航到 user/bar,原來的組件實例會被複用。由於兩個路由都渲染同個組件,比起銷燬再建立,複用則顯得更加高效。不過,這也意味着組件的生命週期鉤子不會再被調用。
複用組件時,想對路由參數的變化做出響應的話,你能夠簡單地 watch(監測變化) $route 對象:
const User = { template: '...', watch: { '$route' (to, from) { // 對路由變化做出響應... } } }
vue-router 使用 path-to-regexp 做爲路徑匹配引擎,因此支持不少高級的匹配模式,例如:可選的動態路徑參數、匹配零個或多個、一個或多個,甚至是自定義正則匹配。查看它的 文檔 學習高階的路徑匹配,還有 這個例子 展現 vue-router 怎麼使用這類匹配。
嵌套路由是個常見的需求,假設用戶可以經過路徑/home/news和/home/message訪問一些內容,一個路徑映射一個組件,訪問這兩個路徑也會分別渲染兩個組件。
藉助 vue-router,使用嵌套路由配置,就能夠很簡單地表達這種關係。
接着上節建立的 app:
<div id="app"> <router-view></router-view> </div> const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
這裏的 <router-view> 是最頂層的出口,渲染最高級路由匹配到的組件。一樣地,一個被渲染組件一樣能夠包含本身的嵌套 <router-view>。例如,在 User 組件的模板添加一個 <router-view>:
const User = { template: ` <div class="user"> <h2>User {{ $route.params.id }}</h2> <router-view></router-view> </div> }
要在嵌套的出口中渲染組件,須要在 VueRouter 的參數中使用 children 配置:
const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, children: [ { // 當 /user/:id/profile 匹配成功, // UserProfile 會被渲染在 User 的 <router-view> 中 path: 'profile', component: UserProfile }, { // 當 /user/:id/posts 匹配成功 // UserPosts 會被渲染在 User 的 <router-view> 中 path: 'posts', component: UserPosts } ] } ] })
除了使用router-link建立標籤a還能夠經過router的實例方法,經過編碼來實現.
如下兩種方式均可以建立一個a標籤:
router.push(...)
router.push向history棧中添加一條數據,用戶點擊back時,回到原來的url
push有如下用法:
router.replace(location) 跟 router.push 很像,惟一的不一樣就是,它不會向 history 添加新記錄,而是跟它的方法名同樣 —— 替換掉當前的 history 記錄。
<router-link to="..." replace> router.replace(...) router.go(n) 方法的參數是一個整數,在 history 記錄中向前或者後退多少步
有時候,經過一個名稱來標識一個路由顯得更方便一些,特別是在連接一個路由,或者是執行一些跳轉的時候。你能夠在建立 Router 實例的時候,在 routes 配置中給某個路由設置名稱。
const router = new VueRouter({ routes: [ { path: '/user/:userId', name: 'user', component: User } ] })
要連接到一個命名路由,能夠給 router-link 的 to 屬性傳一個對象:
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
這跟代碼調用 router.push() 是一回事:
router.push({ name: 'user', params: { userId: 123 }})
這兩種方式都會把路由導航到 /user/123 路徑。
有時候想同時(同級)展現多個視圖,而不是嵌套展現,例如建立一個佈局,有 sidebar(側導航) 和 main(主內容) 兩個視圖,這個時候命名視圖就派上用場了。你能夠在界面中擁有多個單獨命名的視圖,而不是隻有一個單獨的出口。若是 router-view 沒有設置名字,那麼默認爲 default。
<router-view class="view one"></router-view> <router-view class="view two" name="a"></router-view> <router-view class="view three" name="b"></router-view>
一個視圖使用一個組件渲染,所以對於同個路由,多個視圖就須要多個組件。確保正確使用 components 配置(帶上 s):
const router = new VueRouter({ routes: [ { path: '/', components: { default: Foo, a: Bar, b: Baz } } ] })
重定向也是經過 routes 配置來完成,下面例子是從 /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 重定向的 字符串路徑/路徑對象 }} ] })
『重定向』的意思是,當用戶訪問 /a時,URL 將會被替換成 /b,而後匹配路由爲 /b,那麼『別名』又是什麼呢?
/a 的別名是 /b,意味着,當用戶訪問 /b 時,URL 會保持爲 /b,可是路由匹配則爲 /a,就像用戶訪問 /a 同樣。
上面對應的路由配置爲:
const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
『別名』的功能讓你能夠自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構。
項目中我用的是history模式。
默認 hash 模式 —— 使用 URL 的 hash 來模擬一個完整的 URL,因而當 URL 改變時,頁面不會從新加載。
若是不想要很醜的 hash,咱們能夠用路由的 history 模式,這種模式充分利用 history.pushState API 來完成 URL 跳轉而無須從新加載頁面。
const router = new VueRouter({ mode: 'history', routes: [...] })
當你使用 history 模式時,URL 就像正常的 url,例如 http://yoursite.com/user/id,也好看!
不過這種模式要玩好,還須要後臺配置支持。由於咱們的應用是個單頁客戶端應用,若是後臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://oursite.com/user/id 就會返回 404,這就很差看了。
因此呢,你要在服務端增長一個覆蓋全部狀況的候選資源:若是 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。
vue-router 提供的導航鉤子主要用來攔截導航,讓它完成跳轉或取消。有多種方式能夠在路由導航發生時執行鉤子:全局的, 單個路由獨享的, 或者組件級的。
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // do something next(); }); router.afterEach((to, from, next) => { console.log(to.path); });
每一個鉤子方法接收三個參數:
next(): 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是confirmed (確認的)。
next(false): 中斷當前的導航。若是瀏覽器的 URL 改變了(多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from路由對應的地址。
next('/') 或者 next({ path: '/' }): 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。
確保要調用 next方法,不然鉤子就不會被 resolved。
你能夠在路由組件內直接定義如下路由導航鉤子:
beforeRouteEnter beforeRouteUpdate (2.2 新增) beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 由於當鉤子執行前,組件實例還沒被建立 }, beforeRouteUpdate (to, from, next) { // 在當前路由改變,可是該組件被複用時調用 // 舉例來講,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 因爲會渲染一樣的 Foo 組件,所以組件實例會被複用。而這個鉤子就會在這個狀況下被調用。 // 能夠訪問組件實例 `this` }, beforeRouteLeave (to, from, next) { // 導航離開該組件的對應路由時調用 // 能夠訪問組件實例 `this` } }
beforeRouteEnter 鉤子 不能 訪問 this,由於鉤子在導航確認前被調用,所以即將登場的新組件還沒被建立。
不過,你能夠經過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回調,而且把組件實例做爲回調方法的參數。
beforeRouteEnter (to, from, next) { next(vm => { // 經過 `vm` 訪問組件實例 }) }
你能夠 在 beforeRouteLeave 中直接訪問 this。這個 leave 鉤子一般用來禁止用戶在還未保存修改前忽然離開。能夠經過 next(false) 來取消導航。
<div id="app"> <p> <router-link to="/foo">首頁</router-link> <router-link to="/bar">關於咱們</router-link> <router-link to="/user">帳戶中心</router-link> <router-link to="/user/pwd">密碼管理</router-link> <router-link to="/login">登陸</router-link> <input type="button" value="logout" @click="logout"> </p> <router-view></router-view> </div> <template id="logintpl"> <div> <input type="button" value="login" @click="login"> </div> </template> <script> var Foo = { template:"<div>我是首頁</div>" } var Bar = { template:"<div>我是關於咱們</div>" } var User = { template:"<div>我是帳戶中心<router-view></router-view></div>" } var Pwd = { template:"<div>我是密碼</div>" } var routes = [ //我是首頁 {path:"/foo" , component:Foo}, //我是關於咱們 {path:"/bar" , component:Bar}, //我是帳戶中心 { path:"/user" , meta:{requireLogin:true}, component:User, children:[ { //我是密碼 path:"pwd" , meta:{requireLogin:true}, component:Pwd } ] }, //我是登陸 { path:"/login" , component:{ template:"#logintpl", methods:{ login:function(){ isLogin = true } } } } ] var router = new VueRouter({ routes }) var isLogin = true ; router.beforeEach((to, from, next) => { if(to.meta.requireLogin&&!isLogin){ next("/login") }else{ next(); } }) var app = new Vue({ el:"#app", router, methods:{ logout:function(){ isLogin = false } } }); </script>