html:javascript
<script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <div id="app"> <h1>Hello App!</h1> <p> <!-- 使用 router-link 組件來導航. --> <!-- 經過傳入 `to` 屬性指定連接. --> <!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 --> <router-link to="/foo">Go to Foo</router-link> <router-link to="/bar">Go to Bar</router-link> </p> <!-- 路由出口 --> <!-- 路由匹配到的組件將渲染在這裏 --> <router-view></router-view> </div>
JavaScript:html
// 0. 若是使用模塊化機制編程,導入Vue和VueRouter,要調用 Vue.use(VueRouter) // 1. 定義(路由)組件。 // 能夠從其餘文件 import 進來 const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } // 2. 定義路由 // 每一個路由應該映射一個組件。 其中"component" 能夠是 // 經過 Vue.extend() 建立的組件構造器, // 或者,只是一個組件配置對象。 // 咱們晚點再討論嵌套路由。 const routes = [ { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] // 3. 建立 router 實例,而後傳 `routes` 配置 // 你還能夠傳別的配置參數, 不過先這麼簡單着吧。 const router = new VueRouter({ routes // (縮寫)至關於 routes: routes }) // 4. 建立和掛載根實例。 // 記得要經過 router 配置參數注入路由, // 從而讓整個應用都有路由功能 const app = new Vue({ router }).$mount('#app') // 如今,應用已經啓動了!
經過注入路由,咱們能夠用 this.$router
來訪問它,就像在任何組件裏用 this.$router
訪問當前路有同樣。前端
export default { computed: { username () { // 咱們很快就會看到 `params` 是什麼 return this.$route.params.username } }, methods: { goBack () { window.history.length > 1 ? this.$router.go(-1) : this.$router.push('/') } } }
const router = new VueRouter({ routes: [ { path: '/user/:userId', name: 'user', component: User } ] })
要連接到一個命名路由,能夠給 router-link
的 to
屬性傳一個對象:vue
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>
這跟代碼調用 router.push()
是一回事:html5
router.push({ name: 'user', params: { userId: 123 }})
這兩種方式都會把路由導航到 /user/123
路徑。java
const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] })
重定向的目標也能夠是一個命名的路由:vue-router
const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] })
甚至是一個方法,動態返回重定向目標:編程
const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { // 方法接收 目標路由 做爲參數 // return 重定向的 字符串路徑/路徑對象 }} ] })
別名:/a
的別名是 /b
,意味着,當用戶訪問 /b
時,URL 會保持爲 /b
,可是路由匹配則爲 /a
,就像用戶訪問 /a
同樣。api
const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
『別名』的功能讓你能夠自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構。瀏覽器
方式一:
const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
方式二:
const User = { props: ['id'], template: '<div>User {{ id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User, props: true }, // 對於包含命名視圖的路由,你必須分別爲每一個命名視圖添加 `props` 選項: { path: '/user/:id', components: { default: User, sidebar: Sidebar }, props: { default: true, sidebar: false } } ] })
若是
props
被設置爲true
,route.params
將會被設置爲組件屬性。
const router = new VueRouter({ mode: 'history', routes: [...] })
404 錯誤頁面配置:
const router = new VueRouter({ mode: 'history', routes: [ { path: '*', component: NotFoundComponent } ] })
定義路由的時候能夠配置 meta
字段:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, children: [ { path: 'bar', component: Bar, // a meta field meta: { requiresAuth: true } } ] } ] })
<transition> <router-view></router-view> </transition>
上面的用法會給全部路由設置同樣的過渡效果,若是你想讓每一個路由組件有各自的過渡效果,能夠在各路由組件內使用 <transition>
並設置不一樣的 name。
const Foo = { template: ` <transition name="slide"> <div class="foo">...</div> </transition> ` } const Bar = { template: ` <transition name="fade"> <div class="bar">...</div> </transition> ` }
設置 連接激活時使用的 CSS 類名。默認值能夠經過路由的構造選項 linkActiveClass
來全局配置。
<router-link class="uilink" :to="{name:'orgList'}" active-class="active">成員</router-link>
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.push(...)
// 字符串 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
或手寫完整的帶有參數的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
router.go(n)
// 在瀏覽器記錄中前進一步,等同於 history.forward() router.go(1) // 後退一步記錄,等同於 history.back() router.go(-1) // 前進 3 步記錄 router.go(3) // 若是 history 記錄不夠用,那就默默地失敗唄 router.go(-100) router.go(100)
有時候想同時(同級)展現多個視圖,而不是嵌套展現,例如建立一個佈局,有 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 } } ] })
你可使用 router.beforeEach
註冊一個全局前置守衛:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
每一個守衛方法接收三個參數:
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。
你也能夠註冊全局後置鉤子,然而和守衛不一樣的是,這些鉤子不會接受 next
函數也不會改變導航自己:
router.afterEach((to, from) => { // ... })
你能夠在路由配置上直接定義 beforeEnter
守衛:
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
這些守衛與全局前置守衛的方法參數是同樣的。
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` } }
有時候,進入某個路由後,須要從服務器獲取數據。例如,在渲染用戶信息時,你須要從服務器獲取用戶的數據。咱們能夠經過兩種方式來實現:
導航完成以後獲取:先完成導航,而後在接下來的組件生命週期鉤子中獲取數據。在數據獲取期間顯示『加載中』之類的指示。
導航完成以前獲取:導航完成前,在路由進入的守衛中獲取數據,在數據獲取成功後執行導航。
<template> <div class="post"> <div class="loading" v-if="loading"> Loading... </div> <div v-if="error" class="error"> {{ error }} </div> <div v-if="post" class="content"> <h2>{{ post.title }}</h2> <p>{{ post.body }}</p> </div> </div> </template> export default { data () { return { loading: false, post: null, error: null } }, created () { // 組件建立完後獲取數據, // 此時 data 已經被 observed 了 this.fetchData() }, watch: { // 若是路由有變化,會再次執行該方法 '$route': 'fetchData' }, methods: { fetchData () { this.error = this.post = null this.loading = true // replace getPost with your data fetching util / API wrapper getPost(this.$route.params.id, (err, post) => { this.loading = false if (err) { this.error = err.toString() } else { this.post = post } }) } } }
經過這種方式,咱們在導航轉入新的路由前獲取數據。咱們能夠在接下來的組件的 beforeRouteEnter
守衛中獲取數據,當數據獲取成功後只調用 next
方法。
export default { data () { return { post: null, error: null } }, beforeRouteEnter (to, from, next) { getPost(to.params.id, (err, post) => { next(vm => vm.setData(err, post)) }) }, // 路由改變前,組件就已經渲染完了 // 邏輯稍稍不一樣 beforeRouteUpdate (to, from, next) { this.post = null getPost(to.params.id, (err, post) => { this.setData(err, post) next() }) }, methods: { setData (err, post) { if (err) { this.error = err.toString() } else { this.post = post } } } }
使用前端路由,當切換到新路由時,想要頁面滾到頂部,或者是保持原先的滾動位置,就像從新加載頁面那樣。 vue-router
能作到,並且更好,它讓你能夠自定義路由切換時頁面如何滾動。
注意: 這個功能只在支持 history.pushState
的瀏覽器中可用。
當建立一個 Router 實例,你能夠提供一個 scrollBehavior
方法:
const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { // return 指望滾動到哪一個的位置 } })
scrollBehavior
方法接收 to
和 from
路由對象。第三個參數 savedPosition
當且僅當 popstate
導航 (經過瀏覽器的 前進/後退 按鈕觸發) 時纔可用。
這個方法返回滾動位置的對象信息,長這樣:
{ x: number, y: number }
{ selector: string, offset? : { x: number, y: number }}
(offset 只在 2.6.0+ 支持)若是返回一個 falsy (譯者注:falsy 不是 false
,參考這裏)的值,或者是一個空對象,那麼不會發生滾動。
舉例:
scrollBehavior (to, from, savedPosition) { return { x: 0, y: 0 } }
對於全部路由導航,簡單地讓頁面滾動到頂部。
返回 savedPosition
,在按下 後退/前進 按鈕時,就會像瀏覽器的原生表現那樣:
scrollBehavior (to, from, savedPosition) { if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }
若是你要模擬『滾動到錨點』的行爲:
scrollBehavior (to, from, savedPosition) { if (to.hash) { return { selector: to.hash } } }