[Vue.js] 筆記 - Vue-Route

使用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 進來
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