點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Dynamic Router Matching 以 Route 為參數

Sam Xiao's Avatar 2021-04-20

在實務上 Route 也會如 RESTful API 一樣,動態在 Route 中夾帶 Data,此時可使用 Dynamic Route Matching,而不用將 Route 寫死。

Version

Vue 3.0.11
Vue Router 4.0.6

Dynamic Router Matching

param000

Data 以 route 形式傳入並在 HTML 顯示。

router/index.js

import { createRouter, createWebHistory } from 'vue-router'
import Home from '/src/components/Home.vue'
import About from '/src/components/About.vue'
import Product from '/src/components/Products.vue'

let history = createWebHistory()
let routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  },
  {
    path: '/products/:name',
    name: 'Product',
    component: Product
  }
]

export default createRouter({ history, routes })

18 行

{
  path: '/products/:name',
  name: 'Product',
  component: Product
}

path 加上 /products/:name,其中 name 為 param,前面加上 :

Component

Products.vue

<template lang='pug'>
div {{ name }}
</template>

<script setup>
import { useRoute } from 'vue-router'

let { params: { name }} = useRoute()
</script>

第 8 行

let { params: { name }} = useRoute()

useRoute() destructure 出 name

param001

<router-link> 使用 dynamic router matching。

App.vue

<template lang='pug'>
RouterLink(:to='{ name: "Product", params: { name: "apple" }}') Product
RouterView/
</template>

若使用 RouterLink,則需加上 params,並傳入包含參數名稱的 Object。

<template lang='pug'>
RouterLink(:to='{ name: "Product", params: { name }}') Product
RouterView/
</template>

<script setup>
ref: name = 'apple'
</script>

也可使用 data binding 將 state 綁定到 params

Router.push()

param001

Router.push() 使用 dynamic router matching。

<template lang='pug'>
a(@click='onClick', href='#') Product
router-view/
</template>

<script setup>
import { useRouter } from 'vue-router'

let { push } = useRouter()

ref: name = 'apple'
let onClick = () => push({ name: 'Product', params: { name }})
</script>

第 9 行

let { push } = useRouter()

useRouter() destructure 出 push()

12 行

let onClick = () => push({ name: 'Product', params: { name }})

使用 push() 跳轉網頁,以 params 傳入包含參數名稱的 Object。

Point-free

param001

以 Point-free 使用 dynamic router matching。

always()

<template lang='pug'>
a(@click='onClick', href='#') Product
router-view/
</template>

<script setup>
import { useRouter } from 'vue-router'
import { pipe, always } from 'ramda'

let { push } = useRouter()

ref: name = 'apple'

let onClick = pipe(
  always({ name: 'Product', params: { name }}),
  push
)
</script>

14 行

let onClick = pipe(
  always({ name: 'Product', params: { name }}),
  push
)

使用 pipe() 組合出 onClick()

  • always({ name: 'Product', params: { name }}) :準備 argument
  • push:跳轉到指定 name

thunkify()

<template lang='pug'>
a(@click='onClick', href='#') Product
router-view/
</template>

<script setup>
import { useRouter } from 'vue-router'
import { thunkify } from 'ramda'

let { push } = useRouter()

ref: name = 'apple'

let onClick = thunkify(push)({ name: 'Product', params: { name }})
</script>

14 行

let onClick = thunkify(push)({ name: 'Product', params: { name }})

使用 thunkify() 組合出 onClick()

  • thunkify(push):將 push() delay 一個 argument 再傳入

Conclusion

  • Dynamic route matching 讓我們不用將 route 寫死,只要符合特定格式,就可以搭配特定 component
  • Vue router 4 提供了 useRoute()useRouter() 更適合 Composition API 使用

Reference

Vue Router, Dynamic Route Matching with Params