iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
Vue.js

作為 Angular 專家探索 Vue 3 和 Svelte 5系列 第 14

第 13 天- 建立帶有 Prop 的 CoffeePlan 元件

  • 分享至 

  • xImage
  •  

建立 CoffeePlan 元件

第 13 天,我開始將 HTML 程式碼重構為可重用的 CoffeePlan 元件。該元件將接受一個 name 輸入,並在 HTML 模板中顯示該輸入值。

起始 HTML 程式碼

<div class="content">
  <h1 class="title">Coffee Plans</h1>

  <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>

  <div class="plans">
    <div class="plan">
      <div class="description">
        <span class="title"> The Single </span>
      </div>
    </div>

    <div class="plan">
      <div class="description">
        <span class="title"> The Curious </span>
      </div>
    </div>

    <div class="plan">
      <div class="description">
        <span class="title"> The Addict </span>
      </div>
    </div>
  </div>
</div>

以下的 HTML 區塊重複出現四次,僅標題不同,因此可以將其抽取為 CoffeePlan 元件:

<div class="plan">
  <div class="description">
    <span class="title"> The Single </span>
  </div>
</div>

建立不帶 Prop 的 CoffeePlan 元件

Vue 3 應用程式

  • 新建 components/CoffeePlan.vue 檔案並更新模板:
<script setup lang="ts"></script>
<template>
    <div class="plan">
      <div class="description">
        <span class="title"> The Single </span>
      </div>
    </div>
</template>
  • 在 App.vue 中匯入 CoffeePlan:
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
</script>
<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
      </div>
    </div>
</template>
  • 此時畫面上會看到四個標題為 "The Single" 的 CoffeePlan 元件。後續我們將改寫元件以接受不同的標題。

SvelteKit 應用程式

新建 lib/coffee-plan.svelte 檔案並更新模板:

<script lang="ts"></script>
<div class="plan">
  <div class="description">
    <span class="title"> The Single </span>
  </div>
</div>

lib/index.ts 匯出此元件:

export * from './coffee-plan.svelte';

+page.svelte 中匯入 CoffeePlan:

<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';
</script>
<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
        <CoffeePlan />
      </div>
    </div>
</template>

Angular 19 應用程式

建立新的 CoffeePlanComponent

ng g c coffeePlan
@Component({
  selector: 'app-coffee-plan',
  imports: [],
  template: `
    <div class="plan">
        <div class="description">
            <span class="title"> The Single </span>
        </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {}

app.component.ts 中匯入 CoffeePlanComponent

import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';
@Component({
  selector: 'app-root',
  imports: [CoffeePlanComponent],
  template: `
    <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        <app-coffee-plan />
        <app-coffee-plan />
        <app-coffee-plan />
        <app-coffee-plan />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {}

為 CoffeePlan 元件新增 Name Prop

Vue 3 應用程式

  • 定義一個帶預設值和正確類型的 name prop。defineProps 會自動導入,無需明確匯入。
<script setup lang="ts">
defineProps({
    name: {
        type: String,
        default: 'Default Plan',
    },
})
</script>
<template>
    <div class="plan">
      <div class="description">
        <span class="title"> {{ name }} </span>
      </div>
    </div>
</template>
  • 傳遞輸入值給 CoffeePlan 元件:
<script setup lang="ts">
import CoffeePlan from './components/CoffeePlan.vue'
import { ref } from 'vue'
const plans = ref(["The Single", "The Curious", "The Addict", "The Hacker"])
</script>
<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        <CoffeePlan v-for="plan in plans" :key="plan" :name="plan" />
      </div>
    </div>
</template>

SvelteKit 應用程式

  • 定義一個帶預設值和正確類型的 name prop。無需匯入即可使用 $props。
<script lang="ts">
interface Props {
    name: string
}
const { name = 'Default Plan' } = $props();
</script>
<div class="plan">
  <div class="description">
    <span class="title">{name}</span>
  </div>
</div>
  • 傳遞輸入值給 CoffeePlan 元件:
<script lang="ts">
import CoffeePlan from '$lib/coffee-plan.svelte';
const plans = $state(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
</script>
<template>
   <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        {#each plans as plan (plan)}
            <CoffeePlan plan={name} />
        {/each}  
      </div>
    </div>
</template>

Angular 19 應用程式

  • 在 CoffeePlanComponent 中定義 name 的 signal 輸入:
@Component({
  selector: 'app-coffee-plan',
  imports: [],
  template: `
    <div class="plan">
        <div class="description">
            <span class="title">{{ name() }}</span>
        </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CoffeePlanComponent {
    name = input('Default Plan');
}
  • 傳遞輸入值給 CoffeePlanComponent:
import { CoffeePlanComponent } from './coffee-plan/coffee-plan.component';
@Component({
  selector: 'app-root',
  imports: [CoffeePlanComponent],
  template: `
    <div class="content">
      <h1 class="title">Coffee Plans</h1>
      <h2 class="subtitle">We travel the world to source the very best single origin coffee for you</h2>
      <div class="plans">
        @for (plan of plans(); track plan) {
            <app-coffee-plan [name]="plan" />
        }
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent {
    plans = signal(['The Single', 'The Curious', 'The Addict', 'The Hacker']);
}

我們已成功建立一個可重用的 CoffeePlan 元件,並匯入到 App 元件中以顯示不同的方案。

Github Repositories


上一篇
第 12 天 - 開始 Vue 元件入門課程
下一篇
第14天 - 建立 PlanPicker 父元件
系列文
作為 Angular 專家探索 Vue 3 和 Svelte 520
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言