在跳轉頁面時,可以透過路由物件裏 params 或 query 來傳遞資料,也可以使用各種不同模式的 Route props 來傳遞資料。前者需要依賴 URL ,例如 params 需要依靠動態路由,即是/example/:id
來完成。query 則需要在 URL 裏寫 /example?id=123
這樣的格式來傳送。
相反,各種模式的 route props 就比較靈活,不用依賴 URL,而且不用透過 route 物件來取得資料像是 this.$route.params
這樣的寫法就能省下。因為我們可以直接在頁面元件設定 props,直接用意 props 來取得經由路由傳遞過來的資料。
以下會再作詳細解說。
但在進入主題之前,先簡單重溫在 Vue 有什麼方法實現跨頁面資料:
注意,目前討論的情況是跨頁面傳資料,不是父子元件之間傳資料,因此 props/emit
以及 provide/inject
方法就不適用於此情況。
回到重點,此文章會集中說明 route props 的方法。
先說明最簡單的 params 和 query 用法。這也是新手剛學 Vue 時最常用到的方法。
先說明 params,做法是在路由設定參數:
const router = new VueRouter({
routes: [
{ path: '/user/:id', component: User }
]
})
當輸入 /user/111
後,可以在 route object 裏取得 params:
console.log(this.$route.params.id)
// 111
第二種是 query,路由直接設定為 /user
即可。但 URL 必須使用這格式:/user?id=111
。
同樣地,使用 route object 取得由以上路由傳來的 query,結果會回傳一個物件:
console.log(this.$route.query)
// {id: '111'}
$router.push
時,只能擇一填寫 params
或 path
屬性另外提醒,當使用 $router.push()
的方法來跳轉頁面時,要注意:
正確寫法:
const id = '123'
this.$router.push({
name: 'user', // 要事先在 router 那邊命名你的元件
params: { id }
})
或者
this.$router.push({ path: `/user/${id}` })
錯誤寫法:
this.$router.push({
path: '/user',
params: { id }
})
然而,傳 query 的話就沒有此限制:
this.$router.push({
path: '/user',
query: { id }
})
query 所傳送的參數會顯示在 URL 裏,但 params 則不一定。像以下寫法:
const id = "111";
this.$router.push({
name: 'User', // 即是 /user
params: { id }
});
結果會跳轉到 /user
此 URL,在 URL 裏不會顯示 id 的值。反之,使用 query 的話,參數一定會顯示在 URL 裏。
很重要一點,重刷頁面時,如果使用 query 傳參,資料仍然會存在。反之,params 傳參的話,資料就會消失。
說到重點了,如果我要跨頁面傳多筆資料,或者是物件資料。如何使用路由傳參的方法來完成?
如果要傳送多個值,使用 params
和 query
也可。
前者的話,只要在$router.push()
裏的 params
物件裏再塞資料就可以:
this.$router.push({
name: 'User',
params: {
id: 111, // 注意,傳送後會轉為字串
name: 'Alysa'
}
});
query 的做法:
this.$router.push("/user?id=111&name=Alysa")
或
this.$router.push({
path: '/user',
query: {
id: 111, // 注意,傳送後會轉為字串
name: 'Alysa'
}
})
然而,以上示範可見,params 和 query 所傳送的值都會變為字串型別。因此如果值是物件的話,就沒法傳送。不然會變成 "[object Object]"
。這情況下,如果透過 params 來傳資料就會有問題。解決方法會用 JSON.parse
和 JSON.stringify
來轉換資料。
以上示範,我們要用 $route.params
這些方法取得 params 和 query。但如果使用 route props 的各種傳送 route props 的模式,就可以更靈活,不再使用 $router
來取得資料也行!
布林模式,需要設定動態路由以及 props: true
。
以下例子,假設我要把 id 資料,由某一頁傳到 A 元件頁面裏使用。
router/index.js
const routes = [
{
path: "/",
component: Home
},
{
path: "/a/:id",
name: "a",
component: A,
props: true
}
];
A 元件
<template>
<h1>這是 A 頁面</h1>
<p>以下是從首頁傳來的資料:</p>
<p>{{ id }}</p>
</template>
<script>
export default {
props: {
id: {
type: String,
},
},
};
</script>
不用再透過 this.$route.params
來取資料了!直接在元件裏的 props 接收 id 資料,並顯示出來。但注意,元件所接收的 props,只能是 params。
在路由物件裏,建立一個函式來回傳 props,給頁面元件使用。
跟 Boolean mode 明顯不同:
以下先示範傳 params 做法。假設我要做以下的事:
router/index.js
{
path: "/b-params",
name: "Bparams",
component: Bparams,
props: (route) => route.params
}
Home.vue(首頁)
按按鈕後,就跳轉到 Bparams頁面,並把 API 回傳資料用 params 傳出去。
<template>
<h2>Function mode(傳 params)</h2>
<p>按按鈕後打 API,用 function mode,把 API 資料傳到 B-params 頁面</p>
<a href="#" @click.prevent="passDataToB">去 B-params 頁面</a>
</template>
export default {
methods: {
passDataToB() {
fetch("https://randomuser.me/api/")
.then((res) => res.json())
.then((res) => {
this.$router.push({
name: "Bparams",
params: {
...res.results[0],
},
});
})
.catch((err) => console.log(err));
},
},
};
Bparams.vue
<template>
<h1>這是 B 頁面</h1>
<p>以下是從首頁傳來的資料:</p>
<p>{{ user }}</p>
</template>
export default {
props: {
user: {
type: Object,
},
},
};
物件模式適用於傳入靜態資料。直接在 props 物件裏定義要傳送的資料即可。
以下示範把資料傳入 C 頁面元件:
router/index.js
{
path: "/c",
name: "c",
component: C,
// Object mode
props: {
userStatic: {
username: "Tom",
age: 20
}
}
}
C.vue
<template>
<h1>這是 C 頁面</h1>
<p>以下是從 router props 傳來的靜態資料:</p>
<p>{{ userStatic }}</p>
</template>
export default {
props: {
userStatic: {
type: Object,
},
},
};
https://codesandbox.io/s/router-props-function-mode-ktzbr?file=/src/views/Home.vue
this.$router.push()
來跳轉頁面時,如果是傳 params,要注意 path 和 params 屬性不能共存,只能擇一填寫。How to pass Vue Router params as props to components
【Vue.js】Vue Router 之透過路由組件傳參數給元件