vue-router
上篇文章講了第一篇vue-router相關文章,文章地址:VueJs(10)---vue-router(進階1)
一、命名路由
有時候,通過一個名稱來標識一個路由顯得更方便一些,特別是在鏈接一個路由,或者是執行一些跳轉的時候。你可以在創建 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
路徑。
二、命名視圖
1、命名視圖
命名視圖只需兩步:第一在router-view添加name屬性,第二在路由中用components。
有時候想同時(同級)展示多個視圖,而不是嵌套展示,例如創建一個布局,有 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
}
}
]
})
舉例
<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>Named Views</h1> <ul> <li> <router-link to="/">/</router-link> </li> <li> <router-link to="/other">/other</router-link> </li> </ul> <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> </div> <script> const Foo = { template: '<div>foo</div>' } const Bar = { template: '<div>bar</div>' } const Baz = { template: '<div>baz</div>' } const router = new VueRouter({ mode: 'history', routes: [{ path: '/', components: { default: Foo, a: Bar, b: Baz } }, { path: '/other', components: { default: Baz, a: Bar, b: Foo } }] }) new Vue({ router, el: '#app' }) </script>
效果:
2、嵌套命名視圖
我們也有可能使用命名視圖創建嵌套視圖的復雜布局。這時你也需要命名用到的嵌套 router-view
組件。我們以一個設置面板為例:
Nav
只是一個常規組件。UserSettings
是一個視圖組件。UserEmailsSubscriptions
、UserProfile
、UserProfilePreview
是嵌套的視圖組件。
UserSettings
組件的 <template>
部分應該是類似下面的這段代碼:
<!-- UserSettings.vue --> <div> <h1>User Settings</h1> <NavBar/> <router-view/> <router-view name="helper"/> </div>
然后你可以用這個路由配置完成該布局:
{ path: '/settings', // 你也可以在頂級路由就配置命名視圖 component: UserSettings, children: [{ path: 'emails', component: UserEmailsSubscriptions }, { path: 'profile', components: { default: UserProfile, helper: UserProfilePreview } }] }
三、重定向和別名
1、重定向
(1)重定向也是通過 routes
配置來完成,下面例子是從 /a
重定向到 /b
:
const router = new VueRouter({ routes: [ { path: '/a', redirect: '/b' } ] })
(2) 重定向的目標也可以是一個命名的路由:
const router = new VueRouter({ routes: [ { path: '/a', redirect: { name: 'foo' }} ] })
(3)甚至是一個方法,動態返回重定向目標:
const router = new VueRouter({ routes: [ { path: '/a', redirect: to => { // 方法接收 目標路由 作為參數 // return 重定向的 字符串路徑/路徑對象 }} ] })
注意導航守衛並沒有應用在跳轉路由上,而僅僅應用在其目標上。在下面這個例子中,為 /a
路由添加一個 beforeEach
或 beforeLeave
守衛並不會有任何效果。
2、別名
重定向和別名的區別:
重定向:當用戶訪問 /a
時,URL 將會被替換成 /b
,然后匹配路由為 /b
,那么『別名』又是什么呢?
別名:/a
的別名是 /b
,意味着,當用戶訪問 /b
時,URL 會保持為 /b
,但是路由匹配則為 /a
,就像用戶訪問 /a
一樣。
上面對應的路由配置為:
const router = new VueRouter({ routes: [ { path: '/a', component: A, alias: '/b' } ] })
『別名』的功能讓你可以自由地將 UI 結構映射到任意的 URL,而不是受限於配置的嵌套路由結構。
四、路由組件傳參
路由組件傳參一樣需要:props,屬性,通過props我們不用在組件中用{{ $route.params.id }}獲取屬性值,而可以直接把route.params
設置為組件屬性。
使用 props
將組件和路由解耦:
(1) 不用props
const User = { template: '<div>User {{ $route.params.id }}</div>' } const router = new VueRouter({ routes: [ { path: '/user/:id', component: User } ] })
(2)通過 props
解耦
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
將會被設置為組件屬性。
(3)如果 props
是一個對象,它會被按原樣設置為組件屬性。當 props
是靜態的時候有用。
const router = new VueRouter({ routes: [ { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } } ] })
(4)函數模式
你可以創建一個函數返回 props
。這樣你便可以將參數轉換成另一種類型,將靜態值與基於路由的值結合等等。
const router = new VueRouter({ routes: [ { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) } ] })
URL /search?q=vue
會將 {query: 'vue'}
作為屬性傳遞給 SearchUser
組件。
請盡可能保持 props
函數為無狀態的,因為它只會在路由發生變化時起作用。如果你需要狀態來定義 props
,請使用包裝組件,這樣 Vue 才可以對狀態變化做出反應。
五、HTML5 History 模式
vue-router
默認 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 依賴的頁面。
想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要么別想,要么多做。中尉【20】