Vue-vue-router.js路由
一:安裝
在 Vue 後面加載 vue-router
,它會自動安裝的:
<script src="/path/to/vue.js"></script>
<
script src="/path/to/vue-router.js"></script>
二:使用
用 Vue.js + vue-router 創建單頁應用,是非常簡單的。使用 Vue.js ,我們已經可以通過組合組件來組成應用程序,當你要把 vue-router 添加進來,我們需要做的是,將組件(components)映射到路由(routes),然後告訴 vue-router 在哪裏渲染它們。下面是個基本例子:
HTML
<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
// 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‘)
// 現在,應用已經啟動了!
三:
動態路由匹配
我們經常需要把某種模式匹配到的所有路由,全都映射到同個組件。例如,我們有一個 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
怎麽使用這類匹配。
匹配優先級
有時候,同一個路徑可以匹配多個路由,此時,匹配的優先級就按照路由的定義順序:誰先定義的,誰的優先級就最高。
四:嵌套路由
實際生活中的應用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態路徑也按某種結構對應嵌套的各層組件,例如:
/user/foo/profile /user/foo/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
借助 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
}
]
}
]
})
要註意,以 /
開頭的嵌套路徑會被當作根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。
你會發現,children
配置就是像 routes
配置一樣的路由配置數組,所以呢,你可以嵌套多層路由。
此時,基於上面的配置,當你訪問 /user/foo
時,User
的出口是不會渲染任何東西,這是因為沒有匹配到合適的子路由。如果你想要渲染點什麽,可以提供一個 空的 子路由:
const router = new VueRouter({
routes: [
{
path: ‘/user/:id‘, component: User,
children: [
// 當 /user/:id 匹配成功,
// UserHome 會被渲染在 User 的 <router-view> 中
{ path: ‘‘, component: UserHome },
// ...其他子路由
]
}
]
})
五:編程式的導航
除了使用 <router-link>
創建 a 標簽來定義導航鏈接,我們還可以借助 router 的實例方法,通過編寫代碼來實現。
router.push(location)
想要導航到不同的 URL,則使用 router.push
方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前的 URL。
當你點擊 <router-link>
時,這個方法會在內部調用,所以說,點擊 <router-link :to="...">
等同於調用 router.push(...)
。
聲明式 | 編程式 |
---|---|
<router-link :to="..."> |
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‘ }})
router.replace(location)
跟 router.push
很像,唯一的不同就是,它不會向 history 添加新記錄,而是跟它的方法名一樣 —— 替換掉當前的 history 記錄。
聲明式 | 編程式 |
---|---|
<router-link :to="..." replace> |
router.replace(...) |
router.go(n)
這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似 window.history.go(n)
。
例子
// 在瀏覽器記錄中前進一步,等同於 history.forward()
router.go(1)
// 後退一步記錄,等同於 history.back()
router.go(-1)
// 前進 3 步記錄
router.go(3)
// 如果 history 記錄不夠用,那就默默地失敗唄
router.go(-100)
router.go(100)
操作 History
你也許註意到 router.push
、 router.replace
和 router.go
跟 window.history.pushState
、 window.history.replaceState
和 window.history.go
好像, 實際上它們確實是效仿 window.history
API 的。
因此,如果你已經熟悉 Browser History APIs,那麽在 vue-router 中操作 history 就是超級簡單的。
還有值得提及的,vue-router 的導航方法 (push
、 replace
、 go
) 在各類路由模式(history
、 hash
和 abstract
)下表現一致。
六:命名路由
有時候,通過一個名稱來標識一個路由顯得更方便一些,特別是在鏈接一個路由,或者是執行一些跳轉的時候。你可以在創建 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,而不是受限於配置的嵌套路由結構。
更多高級用法,請查看 例子.
Vue-vue-router.js路由