使用Vue Route簡單的實作SPA
以下會包含幾個部分
1.VueRouter 基礎使用
2.巢狀Route
3.在一個 Route 中指定多個 router-view
4.指定路由名稱
5.指定路由別名
6.指定路由 Redirect 到其他 route
7.讓 .vue 解除對 VueRouter 的相依
8.Router Mode
這個範例使用 vue-cli 產生簡單的專案範本,選擇default的設定
npm i -s vue-router
vue create <SampleName>
建立後可以在終端機執行 npm run serve,執行應用(相關設定在package.json裡面)
npm run serve
單層Route
1.為 main.js 加上 router 定義
- import VueRouter form "vue-router"
- Vue.use(VueRouter)
- 在 new Vue({ ... })裡面加上 router,內容則是 new VueRouter({ ... })
- 裡面的 routers 是一個 [ ],用來定義各個 route
- path 代表在網址上的路徑,第一層的route需要在前面加上 "/"
- component 代表這個路徑要載入哪一個 component 進來
- 裡面的 routers 是一個 [ ],用來定義各個 route
import Vue from 'vue'
import App from './App.vue'
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld";
import About from "./components/About";
Vue.use(VueRouter);
Vue.config.productionTip = false
new Vue({
router: new VueRouter({
routes: [
{path: "", component: HelloWorld},
{path: "/About", component: About},
]
}),
render: h => h(App),
}).$mount('#app')
2.調整 App.vue(相當於 index 之類的頁面)
- 在html模板上,可以使用 VueRouter提供的 <router-link> 並設定 to 來產生對應的連結
- router-view 則是在定義上面定義的 component 會顯示的位置
<template>
<div>
<div>App</div>
<hr>
<div>
<router-link to="/">Home</router-link>
</div>
<div>
<router-link to="/About">About</router-link>
</div>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
}
</script>
<!--About.vue-->
<template>
<div>About</div>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
3.這時的應用已經可以做兩個頁面的切換了
4.接著我們新增新的 component,我希望他可以從網址取得一個參數 id
- 在Route上,可以在path上加上 :id,定義參數id是一個變數(或是其他的名稱,不限定)
- 在 .vue 上,可以使用 this.$route.params.id 來取得 id 的值
- 如果想取得的值來自QueryString,可以使用 this.$route.query.id
// main.js
new Vue({
router: new VueRouter({
routes: [
{path: "", component: HelloWorld},
{path: "/About", component: About},
{path: "/Detail/:id", component: Detail},
]
}),
<!-- Detail.vue -->
<template>
<div>
<div>Detail</div>
<div>id: {{id}}</div>
</div>
</template>
<script>
export default {
name: "Detail",
computed: {
id() {
return this.$route.params.id;
}
}
}
</script>
5.這時若連結是 /Detail,沒有帶 id 進去,會發現並沒有載入 Detail.vue 這個component的,因為Route上指定的 id 是一個必須的參數,可以在參數後面加上問號,指定這個參數是可選的,這樣即時沒有 id,也可以找到Detail組件並載入顯示
{path: "/Detail/:id?", component: Detail}
6.關於Route上path的設定,可以參考這個連結
巢狀Route
1.可以設定巢狀的 route,以及多個 router-view
- routes內的item可以加上屬性 children(array) 來定義他底下的 routes,底下 route 的屬性跟前一層的相同,需要注意的是 path 開頭不需要 "/"
- 在About.vue 上面也加上了 router-link 以及 router-veiw
// main.js
router: new VueRouter({
routes: [
{path: "", component: HelloWorld},
{
path: "/About", component: About, children: [
{path: "Us", component: AboutUs},
{path: "You", component: AboutYou},
]
},
{path: "/Detail/:id?", component: Detail},
]
}),
<!-- About.vue -->
<template>
<div>
<div>About</div>
<div>
<div>
<router-link to="/About/us">us</router-link>
</div>
<div>
<router-link to="/About/you">you</router-link>
</div>
</div>
<hr>
<router-view></router-view>
</div>
</template>
<!-- AboutUs -->
<template>
<div>AboutUs</div>
</template>
<!-- AboutYou -->
<template>
<div>AboutYou</div>
</template>
2.現在的應用也加上了巢狀的routes設定
3.若要定義 About 為選擇任何 link 時的預設顯示的 component,可以加上空 path 的route
routes: [
{path: "/about", component: About, children:[
{path: "", component: home},
{path: "us", component: us},
{path: "you", component: you},
]},
]
在一個 Route 中指定多個 router-view
1.一個 Component 上要控制的組件可能有多個時,可以在 Route 上設定 Components 指定多個組件,並且在 .vue 中給 router-view 指定 name
- 在 components 中指定名稱,以及對應的 component
- router-view 加上 name 指定名稱
{
path: "/About", name: "Test", component: About, children: [
{
path: "Us", components: {
Test1: AboutUs,
Test2: Test2,
}
}]
}
<template>
<div>
<div>About</div>
<div>
<div>
<router-link to="/About/us">us</router-link>
</div>
<div>
<router-link to="/About/you">you</router-link>
</div>
</div>
<hr>
<router-view name="Test1"></router-view>
<router-view name="Test2"></router-view>
</div>
</template>
2.若未指定 router-view 的名稱,預設的名稱將會是 "default",在只有指定單一組件時,也可以在 default的 router-view 上顯示組件內容
{
path: "/About", name: "Test", component: About, children: [
{
path: "Us", components: {
default: AboutUs,
Test2: Test2,
}
}
{path: "You", component: AboutYou}
<template>
<div>
<div>About</div>
<div>
<div>
<router-link to="/About/us">us</router-link>
</div>
<div>
<router-link to="/About/you">you</router-link>
</div>
</div>
<hr>
<!-- <router-view ></router-view>-->
<router-view name="default"></router-view>
<router-view name="Test2"></router-view>
</div>
</template>
指定路由名稱
1.route的名稱一長,在各個地方要輸入或更改時會變成一個麻煩,故可以在Route上設定名稱,在使用者只就只需要指定名稱即可
- 在html模板使用上,需要改成 v-bind-to="...",內容則是一個物件,並且定義 "name" 為 path上設定的名稱
{ path: "/About", name: "Test", component: About, children: [ {path: "Us", component: AboutUs}, {path: "You", component: AboutYou}, ] }
- 這邊的物件也可以直接指定 params 參數的值,同樣也是一個物件
link :to="{name:'Test', params:{id: 123}}">About</router-link>
指定路由別名
1.若想讓使用者通過不同的連結,進入相同的頁面,可以在 route 上加入別名(alias),若有多個別名,則可以使用array
{path: "/About", alias: "/MyInfo", name: "Test", component: About}
{path: "/About", alias: ["/MyInfo", "Test", "ABC"], name: "Test", component: About}
Redirect
1.符合特定條件的Route,直接指定要Redirect到其他的 Route
- 範例針對所有的path都 redirect 到指定的 route
- Router會按照執行順序,只會走第一個符合條件的 route,故這條 route 之前應該要加上其他的 route
{path: "*", redirect: "/About"},
{path: "*", redirect: {name: "Home"}},
{path: "*", redirect: ()=>"/About"}
讓 .vue 解除對 VueRouter 的相依
在最前面有提到,可以在 .vue 使用 this.$route.params 來取的路由上的參數,但這也倒置了這個 .vue 沒有 VueRouter 就無法執行,故可以改用其他方式讓需要的參數值可以從 props 取得
1.在 route 加上 props 並指定值為 true
2.接著在 .vue 的 props 就能直接取得值了
<!-- .vue -->
<template>
<div>
<div>Detail</div>
<div>id: {{id}}</div>
</div>
</template>
<script>
export default {
name: "Detail",
props: ["id"],
}
</script>
{
path: "/Detail/:id?",
component: Detail,
name: "Item",
props: true
}
2.直接指定 props 內的參數內容
{
path: "/Detail/:id?",
component: Detail,
name: "Item",
props: { id:123 }
}
3.從方法設定值,這邊的 route 即是原本在 .vue 中的 this.$route
- 同時也可以使用 route.query.id 來取得queryString上的值
{
path: "/Detail/:id?",
component: Detail,
name: "Item",
props: (route) => {
return {
id: route.params.id
}
}
}
Router Mode
1.在目前的網址上面,都會看到一個不尋常的 "#" 符號,這是由 Router 的 Mode 產生的(預設的 Mode 為 hash)
http://localhost:8080/#/About/us
2.可以在 new Router({ ... }) 裡面指定 mode,有 hash 跟 histroy 可以選擇
- history 則是一般常見的網址,沒有 "#" 符號,但是會有 url rewrite 的問題,需要再由後端調整設定,讓所有的網址都能轉到 index.html 上,改由 VueRouter 控制畫面的顯示
{
router: new VueRouter({
mode: "history",
})
}
Sample Code https://github.com/ianChen806/VueRouterSample
僅僅是學習筆記罷了xD