本篇文章示範了 Vue 3、SvelteKit 與 Angular 如何使用內建的控管流程語法或指令來進行條件渲染。Vue 3 使用 v-if
、v-else-if
和 v-else
指令來條件渲染,而 Svelte 與 Angular 則使用 if/else-if/else 來在 HTML 模板中條件渲染元素。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ref } from 'vue'
const items = ref<Item[]>([])
const deleteItem = (id: number) => { /* 刪除邏輯同前 */ }
</script>
<template>
<template v-if="items.length > 0">
<ul>
<div class="list-item" v-for="item in items" :key="item.id">
<li>{{ item.id }} - {{ item.label }}</li>
<button aria-label="Delete" @click="deleteItem(item.id)">
<Icon icon="ic:baseline-remove" />
</button>
</div>
</ul>
</template>
<p v-else>Nothing to see here.</p>
</template>
這裡將無序列表包裹在 <template> 元素內,並在該元素上加上 v-if="items.length > 0
指令。當 items 陣列長度大於 0 時,顯示此列表;反之則顯示一段文字 "Nothing to see here." 透過 v-else
指令達成。
<script lang="ts">
import Icon from '@iconify/svelte';
let items = $state([] as Item[]);
function deleteItem(id: number) { /* 刪除邏輯同前 */ }
</script>
{#if items.length > 0}
<ul>
{#each items as item (item.id)}
<div class="list-item">
<li>{item.id} - {item.label}</li>
<button onclick={() => deleteItem(item.id)} aria-label="delete an item">
<Icon icon="ic:baseline-remove" />
</button>
</div>
{/each}
</ul>
{:else}
<p>Nothing to see here</p>
{/if}
使用 {#if}
包裹清單,當 items
不為空陣列時顯示清單,否則使用 {:else}
顯示文字。
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { matRemove, matAdd, matSave } from '@ng-icons/material-icons/baseline';
@Component({
selector: 'app-shopping-cart',
imports: [FormsModule, NgIcon],
viewProviders: [provideIcons({ matRemove, matAdd, matSave })],
template: `
@if (items().length > 0) {
<ul>
@for (item of items(); track item.id) {
<div class="list-item">
<li>{{ item.id }} - {{ item.label }}</li>
<button aria-label="Delete an item" (click)="deleteItem(item.id)">
<ng-icon name="matRemove"></ng-icon>
</button>
</div>
}
</ul>
} @else {
<p>Nothing to see here.</p>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShoppingCartComponent {
items = signal<Item[]>([]);
deleteItem(id: number) { /* 刪除邏輯同前 */ }
}
Angular 17 引入了新的控管流程語法,使用 @if
與 @else
來條件渲染。當 items
信號陣列不空時展示列表,否則展示文字。
新增 isEditing
這個 ref
來保存新增項目表單的狀態。當 isEditing
為 true
時,表單顯示且可編輯;為 false 時,表單隱藏不可編輯。
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { ref } from 'vue'
const items = ref<Item[]>([])
const newItem = ref('')
const newItemHighPriority = ref(false)
const saveItem = () => {
/* 儲存邏輯同前 */
}
const isEditing = ref(false)
const toggleEditing = (value: boolean) => {
isEditing.value = value
newItem.value = ''
newItemHighPriority.value = false
}
</script>
<div class="header">
<button v-if="isEditing" @click="toggleEditing(false)" aria-label="Cancel">
<Icon icon="ic:outline-close" />
</button>
<button v-else @click="toggleEditing(true)" aria-label="Add Item">
<Icon icon="ic:outline-add" />
</button>
</div>
<form v-if="isEditing" @submit.prevent="saveItem">
<input v-model.trim="newItem" placeholder="Add new item" />
<label>
<input type="checkbox" v-model="newItemHighPriority" />
<span> High Priority</span>
</label>
<button aria-label="Save Item">
<Icon icon="ic:outline-save" />
</button>
</form>
按下 "Add Item" 按鈕時,isEditing
會被設為 true,表單顯示且可編輯,並顯示 "Cancel" 按鈕。點擊 "Cancel" 時,toggleEditing
函式會將 isEditing
設為 false,表單隱藏,按鈕切換回 "Add Item"。
<script lang="ts">
import Icon from '@iconify/svelte';
let newItem = $state('');
let newItemHigherPriority = $state(false);
let items = $state([] as Item[]);
let isEditing = $state(false);
function saveItem() { /* 儲存邏輯同前 */ }
async function handleSubmit(event: SubmitEvent) {
/* 儲存邏輯同前 */
}
function toggleEdit(value: boolean) {
isEditing = value;
newItem = '';
newItemHigherPriority = false;
}
</script>
<div class="header">
{#if isEditing}
<button onclick={() => toggleEdit(false)} aria-label="Cancel">
<Icon icon="ic:outline-close" />
</button>
{:else}
<button onclick={() => toggleEdit(true)} aria-label="Add Item">
<Icon icon="ic:outline-add" />
</button>
{/if}
</div>
{#if isEditing}
<form method="POST" onsubmit={handleSubmit}>
<input id="newItem" name="newItem" type="text" placeholder="Add item" bind:value={newItem} />
<label>
<input id="newItemHigherPriority" name="newItemHigherPriority" type="checkbox" bind:checked={newItemHigherPriority} />
<span> Higher Priority</span>
</label>
<button aria-label="Save Item">
<Icon icon="ic:outline-save" />
</button>
</form>
{/if}
當 isEditing
為 true,表單顯示可編輯,並顯示 "Cancel" 按鈕;按下 "Cancel" 會關閉表單。當 isEditing
為 false,表單隱藏,顯示 "Add Item" 按鈕。
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { matAdd, matRemove, matSave } from '@ng-icons/material-icons/baseline';
@Component({
selector: 'app-shopping-cart',
imports: [FormsModule, NgIcon],
viewProviders: [provideIcons({ matRemove, matAdd, matSave })],
template: `
<div class="header">
@if (isEditing()) {
<button (click)="toggleEditing(false)" aria-label="Cancel">
<ng-icon name="matRemove"></ng-icon>
</button>
} @else {
<button (click)="toggleEditing(true)" aria-label="Add Item">
<ng-icon name="matAdd"></ng-icon>
</button>
}
</div>
@if (isEditing()) {
<form class="add-item-form" (ngSubmit)="saveItem()">
<input type="text" placeholder="Add new item" name="newItem" [(ngModel)]="newItem" />
<label>
<input type="checkbox" [(ngModel)]="newItemHighPriority" name="newItemHighPriority" />
<span> High Priority</span>
</label>
<button type="submit" aria-label="Save Item">
<ng-icon name="matSave"></ng-icon>
</button>
</form>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ShoppingCartComponent {
items = signal<Item[]>([]);
newItem = signal('');
newItemHighPriority = signal(false);
isEditing = signal(false);
toggleEditing(value: boolean) {
this.isEditing.set(value);
this.newItem.set('');
this.newItemHighPriority.set(false);
}
saveItem() { /* 儲存邏輯同前 */ }
}
isEditing
信號用來控制新增項目表單的顯示與隱藏。當 isEditing
為 true,表單顯示且可編輯,取消按鈕出現;當 isEditing
為 false,顯示 "Add Item" 按鈕,表單隱藏。