點燈坊

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

Vue Router 之 Props

Sam Xiao's Avatar 2019-06-18

雖然我們可以使用 this.$route 去存取目前 Route,但開發 Component 時,你無法確認 User 是否使用 Vue Router,畢竟 Vue Router 是選配,也無法確認會用什麼 Params 或 Query String,比較好的方式還是回歸 Component 正統設計方式:使用 Props。

Version

macOS Mojave 10.14.5
Node 12.4.0
Vue CLI 3.8.4
Vue 2.6.10

$route

prop000

  1. 當網址為 /products/1
  2. 顯示 Product component 的 T-Shirts

router.js

import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
    },
    {
      path: '/products/:id?',
      name: 'products',
      component: () => import(/* webpackChunkName: "products" */ './views/Products.vue'),
    },
  ]
});

19 行

{
  path: '/products/:id?',
  name: 'products',
  component: () => import(/* webpackChunkName: "products" */ './views/Products.vue'),
}

path 使用 id param。

Product.vue

<template>
  <div>
    <h1>Products</h1>
    <h2>{{ product }}</h2>
  </div>
</template>

<script>
let products = {
  0: 'Shoes',
  1: 'T-Shirts',
  2: 'Pants',
};

let product = function() {
  return products[this.$route.params.id] || 'N/A';
};

export default {
  name: 'Products',
  computed: {
    product,
  },
};
</script>

15 行

let product = function() {
  return products[this.$route.params.id] || 'N/A';
};

需使用 this.$route 存取 route,也就是 component 與 Vue Router 耦合。

以 component 角度,並不確定 user 一定有使用 Vue Router,也不確定是否使用 params 傳進資料,若 component 這樣寫,重複使用程度就很低,比較好的方式是改用 props。

By Boolean

router.js

{
  path: '/products/:id?',
  name: 'products',
  component: () => import(/* webpackChunkName: "products" */ './views/Products.vue'),
  props: true,
},

path 寫法不變,加上 props: true,表示 Vue Router 會將 id 以 props 傳進 products component。

Products.vue

<template>
  <div>
    <h1>Products</h1>
    <h2>{{ product }}</h2>
  </div>
</template>

<script>
let products = {
  0: 'Shoes',
  1: 'T-Shirts',
  2: 'Pants',
};

let product = function() {
  return products[this.id] || 'N/A';
};

export default {
  name: 'Products',
  props: [
    'id'
  ],
  computed: {
    product,
  },
};
</script>

21 行

props: [
  'id'
],

新增 id props。

15 行

let product = function() {
  return products[this.id] || 'N/A';
};

由原本的 this.$route.params.id 改成 this.id

其中 id 是 props, component 就不跟 Vue Router 耦合了。

By Object

router.js

{
  path: '/products/:id?',
  name: 'products',
  component: () => import(/* webpackChunkName: "products" */ './views/Products.vue'),
  props: { id: 1 },
},

props property 改傳入 object,id 為 props。

若想由 router.js 傳入固定值給 component,這是個好方法

Product.vue 寫法不變。

By Function

router.js

{
  path: '/products/:id?',
  name: 'products',
  component: () => import(/* webpackChunkName: "products" */ './views/Products.vue'),
  props: route => ({ id: route.params.id }),
},

Props 也可使用 function,傳入 route,回傳 object,直接對 props 操作。

這種寫法最靈活,若要在 router.js 傳入的 props 有邏輯,則建議使用此方法

Conclusion

  • Vue Router 支援 component 的 props,除了最基本的 boolean 外,還支援了 object 與 function
  • By object 可讓我們在 router 自行傳入資料客製化 component
  • By function 則最靈活,我們可直接在 arrow function 寫邏輯改變要傳入的 props,甚至搭配 higher order function 與 closure 產生 props

Sample Code

完整範例可在我的 GitHub 上找到

Reference

Vue Router, Passing Props to Route Components