第 24 天 - Alert 元件 第 3 部分 - 新增用於更換樣式的 Alert Bar
在第 24 天,我建立了一個 Alert Bar 元件,用來顯示或隱藏關閉按鈕,套用新的樣式到警示訊息並改變它們的方向。
建立一個 icons/CloseIcon.vue
<template>
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.29289 5.29289C5.68342 4.90237 6.31658 4.90237 6.70711 5.29289L12 10.5858L17.2929 5.29289C17.6834 4.90237 18.3166 4.90237 18.7071 5.29289C19.0976 5.68342 19.0976 6.31658 18.7071 6.70711L13.4142 12L18.7071 17.2929C19.0976 17.6834 19.0976 18.3166 18.7071 18.7071C18.3166 19.0976 17.6834 19.0976 17.2929 18.7071L12 13.4142L6.70711 18.7071C6.31658 19.0976 5.68342 19.0976 5.29289 18.7071C4.90237 18.3166 4.90237 17.6834 5.29289 17.2929L10.5858 12L5.29289 6.70711C4.90237 6.31658 4.90237 5.68342 5.29289 5.29289Z" fill="#0F1729"></path>
</svg>
</template>
在 Alert
元件中顯示關閉圖示。
<script setup lang="ts">
import CloseIcon from '@/icons/CloseIcon.vue'
</script>
<template>
... omitted to save space ...
<div>
<button class="btn btn-sm btn-primary" title="Close button" @click="closeAlert">
<CloseIcon />
</button>
</div>
</template>
匯入 CloseIcon
並在 <template>
標籤內加入 <CloseIcon>
,以在按鈕上呈現關閉圖示。
建立一個 lib/icons/close-icon.svelte
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.29289 5.29289C5.68342 4.90237 6.31658 4.90237 6.70711 5.29289L12 10.5858L17.2929 5.29289C17.6834 4.90237 18.3166 4.90237 18.7071 5.29289C19.0976 5.68342 19.0976 6.31658 18.7071 6.70711L13.4142 12L18.7071 17.2929C19.0976 17.6834 19.0976 18.3166 18.7071 18.7071C18.3166 19.0976 17.6834 19.0976 17.2929 18.7071L12 13.4142L6.70711 18.7071C6.31658 19.0976 5.68342 19.0976 5.29289 18.7071C4.90237 18.3166 4.90237 17.6834 5.29289 17.2929L10.5858 12L5.29289 6.70711C4.90237 6.31658 4.90237 5.68342 5.29289 5.29289Z" fill="#0F1729"></path>
</svg>
在 Alert
元件中顯示關閉圖示。
<script lang="ts">
import CloseIcon from '$lib/icons/close-icon.svelte'
</script>
... omitted to save space ...
<div>
<button class="btn btn-sm btn-primary" title="Close button" onclick={closeAlert}>
<CloseIcon />
</button>
</div>
匯入 CloseIcon
,並在 HTML 模板中加入 <CloseIcon />
,以在按鈕上呈現關閉圖示。
建立一個 CloseIconComponent
@Component({
selector: 'app-close-icon',
template: `
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.29289 5.29289C5.68342 4.90237 6.31658 4.90237 6.70711 5.29289L12 10.5858L17.2929 5.29289C17.6834 4.90237 18.3166 4.90237 18.7071 5.29289C19.0976 5.68342 19.0976 6.31658 18.7071 6.70711L13.4142 12L18.7071 17.2929C19.0976 17.6834 19.0976 18.3166 18.7071 18.7071C18.3166 19.0976 17.6834 19.0976 17.2929 18.7071L12 13.4142L6.70711 18.7071C6.31658 19.0976 5.68342 19.0976 5.29289 18.7071C4.90237 18.3166 4.90237 17.6834 5.29289 17.2929L10.5858 12L5.29289 6.70711C4.90237 6.31658 4.90237 5.68342 5.29289 5.29289Z" fill="#0F1729"></path>
</svg>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CloseIconComponent {}
在 Alert
元件中顯示關閉圖示。
import { NgComponentOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, input, output, signal } from '@angular/core';
import { AlertType } from '../alert.type';
import { CloseIconComponent, ErrorIconComponent, InfoIconComponent, SuccessIconComponent, WarningIconComponent } from '../icons/icon.component';
@Component({
selector: 'app-alert',
imports: [NgComponentOutlet, CloseIconComponent],
template: `
... omitted to save space ...
<div>
<button class="btn btn-sm btn-primary" title="Close button" (click)="closeAlert()">
<app-close-icon />
</button>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertComponent {}
匯入 CloseIconComponent
並註冊到 @Component
裝飾器的 imports
陣列中。
在內嵌模板中,使用 app-close-icon
選擇器在按鈕上呈現關閉圖示。
AlertBar
元件中新增顯示/隱藏勾選框自 Vue 3.4 起,推薦的雙向資料綁定方式是使用 defineModel
巨集 (macro)。
<script setup lang="ts">
const hasCloseButton = defineModel<boolean>('hasCloseButton', { default: true })
</script>
宣告一個 defineModel<boolean>
,並將值指派給 hasCloseButton
這個 ref。
{ default: true }
表示該 ref 的預設值為 true,勾選框會被選取,警示元件應顯示關閉按鈕。
<template>
<div>
<p class="mb-[0.75rem]">
<span>Has close button? </span>
<input type="checkbox" class="mr-[0.5rem]" v-model="hasCloseButton" />
</p>
</div>
</template>
在模板中,v-model
指令加入至勾選框輸入元素,並綁定到 hasCloseButton
。
hasCloseButton
啟用雙向資料綁定,並將值傳遞到父元件,即 AlertList
元件。
在 Svelte 5 中,雙向綁定透過 $bindable
函數實現。此外,必須將 $bindable
與 $props
一起使用。我們會更新 Prop
類型,新增 hasCloseButton
,並從 $prop()
呼叫中解構該屬性。
type Props = {
hasCloseButton: boolean;
}
let {
hasCloseButton = $bindable(),
}: Props = $props();
<div>
<p class="mb-[0.75rem]">
<span>Has close button?</span>
<input type="checkbox" class="mr-[0.5rem]" bind:checked={hasCloseButton} />
</p>
</div>
在模板中,勾選框的 bind:checked
屬性綁定到 hasCloseButton
。hasCloseButton
啟用雙向資料綁定,並將值傳遞到父元件,即 AlertList
元件。
在 Angular 中,雙向綁定是透過 model
Writable 信號達成。
import { ChangeDetectionStrategy, Component, input, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-alert-bar',
imports: [],
template: `
<div>
<p class="mb-[0.75rem]">
<span>Has close button? </span>
<input type="checkbox" class="mr-[0.5rem]" [(ngModel)]="hasCloseButton" />
</select>
</p>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertBarComponent {
hasCloseButton = model<boolean>(true);
}
宣告 model<boolean>(true)
並將值指派給 hasCloseButton
信號。model
的預設值為 true,因此勾選框被選取,而 Alert
元件應顯示關閉按鈕。
hasCloseButton
傳遞到 AlertList
元件<script setup lang="ts">
import { computed, ref } from 'vue';
const hasCloseButton = ref(true)
</script>
在 AlertList
元件中宣告 hasCloseButton
ref 以接收來自子元件的值。
Vue 元件允許多重 v-model
綁定。
v-model:hasCloseButton="hasCloseButton"
綁定子元件的 hasCloseButton
屬性到 hasCloseButton
ref。
<template>
<h2>Alert Components (Vue ver.)</h2>
<AlertBar
v-model:hasCloseButton="hasCloseButton"
/>
</template>
Vue 元件允許多重 v-model
綁定。
v-model:hasCloseButton="hasCloseButton"
綁定子元件的 hasCloseButton
屬性到 hasCloseButton
ref。
<script lang="ts">
import AlertBar from './alert-bar.svelte';
let hasCloseButton = $state(true);
</script>
在 AlertList
元件中宣告一個 hasCloseButton
變數以接收來自子元件的值。
<AlertBar {configs}
bind:hasCloseButton={hasCloseButton}
/>
bind:hasCloseButton={hasCloseButton}
表示 AlertList
元件會監聽 AlertBar
元件的 hasCloseButton
屬性變化。
import { ChangeDetectionStrategy, Component, computed, input, signal } from '@angular/core';
import { AlertBarComponent } from '../alert-bar/alert-bar.component';
@Component({
selector: 'app-alert-list',
imports: [AlertBarComponent],
template: `
<app-alert-bar
[(hasCloseButton)]="hasCloseButton"
/>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertListComponent {
hasCloseButton = signal<boolean>(true);
}
在 AlertList
元件中宣告一個 hasCloseButton
信號以接收來自子元件的值。
使用香蕉盒語法 [(expression)]
來對 AlertList
和 AlertBar
元件進行雙向綁定。
const hasCloseButton = ref(true)
const alertConfig = computed(() => ({
hasCloseButton: hasCloseButton.value,
}))
定義一個 alertConfig
計算型 ref,來建立一個物件以儲存 hasCloseButton.value
的值。
<template>
<Alert v-for="{ type, message } in alerts"
class="mb-[0.75rem]"
:key="type"
:type="type"
:alertConfig="alertConfig">
{{ message }}
</Alert>
</template>
將 alertConfig
傳遞給 Alert
元件的 alertConfig
屬性。
<script setup lang="ts">
import { computed, ref } from 'vue'
import CloseIcon from '@/icons/CloseIcon.vue'
type Props = {
alertConfig: {
hasCloseButton: boolean
},
type: string
}
const { type, alertConfig } = defineProps<Props>()
... omit the template codes ...
</script>
在 Alert
元件中,將新的 alertConfig
屬性加入 Prop
類型。 從 defineProps
巨集中解構 alertConfig
。
<template>
<div role="alert" :class="alertClasses" v-if="!closed">
<component :is="icon" />
<span><slot></slot></span>
<div v-if="alertConfig.hasCloseButton">
<button class="btn btn-sm btn-primary" alt="Close button" @click="closeAlert">
<CloseIcon />
</button>
</div>
</div>
</template>
若 alertConfig.hasCloseButton
為 true,則會顯示關閉按鈕,否則隱藏。
<script lang="ts">
import AlertBar from './alert-bar.svelte';
import Alert from './alert.svelte';
import type { AlertMessage } from './alert.type';
let hasCloseButton = $state(true);
</script>
在 AlertList
元件中宣告一個 hasCloseButton
變數以接收來自子元件的值。
{#each alerts as alert (alert.type) }
<Alert {alert} {hasCloseButton} />
{/each}
將 hasCloseButton
變數傳遞給 Alert
元件的 hasCloseButton
屬性。
<AlertBar {configs}
bind:hasCloseButton={hasCloseButton}
/>
bind:hasCloseButton={hasCloseButton}
表示 AlertList
元件會監聽 AlertBar
元件的 hasCloseButton
屬性變化。
<script lang="ts">
type Props = {
... other properties ...
hasCloseButton: boolean;
}
const {
hasCloseButton,
}: Props = $props();
</script>
在 Alert
元件中,將 hasCloseButton
屬性加入 Prop
類型,並從物件中解構此屬性。
{#if !closed}
<div role="alert" class={alertClasses}>
... omit the template code...
{#if hasCloseButton}
<div>
<button class="btn btn-sm btn-primary" title="Close button" onclick={closeAlert}>
<CloseIcon />
</button>
</div>
{/if}
</div>
{/if}
若 hasCloseButton
為 true,則渲染按鈕;否則按鈕隱藏。
import { ChangeDetectionStrategy, Component, computed, input, signal } from '@angular/core';
import { AlertBarComponent } from '../alert-bar/alert-bar.component';
@Component({
selector: 'app-alert-list',
imports: [AlertBarComponent],
template: `
<app-alert-bar
[(hasCloseButton)]="hasCloseButton"
/>
@for (alert of alerts(); track alert.type) {
<app-alert [type]="alert.type"
[alertConfig]="alertConfig()"
>
{{ alert.message }}
</app-alert>
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertListComponent {
hasCloseButton = signal<boolean>(true);
alertConfig = computed(() => ({
hasCloseButton: this.hasCloseButton(),
}));
}
在 AlertList
元件中宣告一個 hasCloseButton
信號以接收來自子元件的值。
使用香蕉盒語法 [(expression)]
,對 AlertList
和 AlertBar
元件進行雙向綁定。
定義一個 alertConfig
計算型信號,用來建立一個物件以儲存 hasCloseButton
信號的值。
將 alertConfig
計算型信號的值指派給 AlertComponent
的輸入信號 (input signal)。
import { NgComponentOutlet } from '@angular/common';
import { ChangeDetectionStrategy, Component, computed, input, output, signal } from '@angular/core';
import { AlertType } from '../alert.type';
import { CloseIconComponent, ErrorIconComponent, InfoIconComponent, SuccessIconComponent, WarningIconComponent } from '../icons/icon.component';
@Component({
selector: 'app-alert',
imports: [NgComponentOutlet, CloseIconComponent],
template: `
@if (!closed()) {
... omit the template codes ...
@if (alertConfig().hasCloseButton) {
<div>
<button class="btn btn-sm btn-primary" title="Close button" (click)="closeAlert()">
<app-close-icon />
</button>
</div>
}
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertComponent {
type = input.required<AlertType>();
alertConfig = input.required<{
hasCloseButton: boolean
}>();
}
在 AlertComponent
中,宣告一個必填輸入信號 alertConfig
。
若 alertConfig().hasCloseButton
為 true,則渲染按鈕,否則按鈕隱藏。
接著,我們將重複相同程序,新增樣式及方向下拉選單,以變更警示元件的樣式。
<script setup lang="ts">
type Props = {
config: {
styleLabel: string
styles: { text: string, value: string }[]
directionLabel: string
directions: { text: string, value: string }[]
},
}
const props = defineProps<Props>()
const { config } = props
</script>
在 AlertBar
元件中宣告 Prop,以接收樣式標籤、樣式下拉選單、方向標籤和方向下拉選單。
const style = defineModel<string>('style', { default: 'color' })
const direction = defineModel<string>('direction', { default: 'horizontal' })
宣告 style
和 direction
這兩個 ref 用於雙向資料綁定。
style
的預設值為 'color'
,direction
的預設值為 'horizontal'
。
<template>
<div>
<p class="mb-[0.75rem]">
<span>{{ config.styleLabel }} </span>
<select class="select select-info mr-[0.5rem]" v-model="style">
<option v-for="{value, text} in config.styles" :key="value" :value="value">
{{ text }}
</option>
</select>
<span>{{ config.directionLabel }} </span>
<select class="select select-info mr-[0.5rem]" v-model="direction">
<option v-for="{ value, text } in config.directions" :key="value" :value="value">
{{ text }}
</option>
</select>
</p>
</div>
</template>
使用 v-for
迭代 config.styles
和 config.directions
,以填充下拉選單的選項項目。
<script lang="ts">
import { capitalize } from './capitalize';
import OpenIcon from './icons/open-icon.svelte';
type Props = {
configs: {
styleLabel: string
styles: { text: string, value: string }[]
directionLabel: string
directions: { text: string, value: string }[]
};
hasCloseButton: string;
style: string;
direction: string;
}
let {
hasCloseButton = $bindable(),
style = $bindable(),
direction = $bindable(),
closedNotifications = $bindable(),
configs
}: Props = $props();
</script>
將 configs
、style
和 direction
新增到 Props
類型中。
從 $props()
解構 style
和 direction
,並使用 $bindable
將它們綁定到 AlertList
元件。
<p class="mb-[0.75rem]">
<span>{ configs.styleLabel } </span> { style }
<select class="select select-info mr-[0.5rem]" bind:value={style}>
{#each configs.styles as s (s.value) }
<option value={s.value}>
{ s.text }
</option>
{/each}
</select>
<span>{ configs.directionLabel } </span>
<select class="select select-info mr-[0.5rem]" bind:value={direction}>
{#each configs.directions as d (d.value)}
<option value={d.value}>
{ d.text }
</option>
{/each}
</select>
</p>
bind:value={style}
將 style
變數綁定到樣式下拉選單。
bind:value={direction}
將 direction
變數綁定到方向下拉選單。
使用 #each
迭代 styles
和 directions
清單,填充下拉選單項目。
@Component({
selector: 'app-alert-bar',
imports: [FormsModule],
template: `... inline template explained below ...`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertBarComponent {
config = input.required<{
styleLabel: string
styles: { text: string, value: string }[]
directionLabel: string
directions: { text: string, value: string }[]
}>();
hasCloseButton = model<boolean>(true);
style = model<string>('color');
direction = model<string>('horizontal');
}
AlertBarComponent
宣告了標籤和下拉選單的必填輸入信號。
同樣地,style
和 direction
被宣告為 model
信號,以實現雙向綁定。
該元件也匯入了 FormsModule
,在內嵌模板中將 model
綁定到 [(ngModel)]
。
<div>
@let c = config();
<p class="mb-[0.75rem]">
<span>{{ c.styleLabel }} </span>
<select class="select select-info mr-[0.5rem]" [(ngModel)]="style">
@for (style of c.styles; track style.value) {
<option [ngValue]="style.value">
{{ style.text }}
</option>
}
</select>
<span>{{ c.directionLabel }} </span>
<select class="select select-info mr-[0.5rem]" [(ngModel)]="direction">
@for (direction of c.directions; track direction.value) {
<option [ngValue]="direction.value">
{{ direction.text }}
</option>
}
</select>
</p>
</div>
[(ngModel)]="style"
將 style
綁定到樣式下拉選單。
同理,[(ngModel)]="direction"
將 direction
綁定到方向下拉選單。
@for
迴圈會遍歷 styles 和 directions 清單,顯示值和文字項目。
config
ref 定義了樣式和方向的標籤及項目。與 hasCloseButton
<script setup lang="ts">
import type { AlertType } from '@/types/alert-type';
import { computed, ref } from 'vue';
import Alert from './Alert.vue';
import AlertBar from './AlertBar.vue';
const hasCloseButton = ref(true)
const style = ref('color');
const direction = ref('horizontal')
const alertConfig = computed(() => ({
style: style.value,
direction: direction.value,
hasCloseButton: hasCloseButton.value,
}))
const config = ref({
styleLabel: "Alert styles:",
styles: [
{ text: 'Default', value: 'color' },
{ text: 'Soft', value: 'soft' },
{ text: 'Outline', value: 'outline' },
{ text: 'Dash', value: 'dash' }
],
directionLabel: "Alert direction:",
directions: [
{ text: 'Horizontal', value: 'horizontal' },
{ text: 'Vertical', value: 'vertical' },
]
})
</script>
類似,style
和 direction
將值從 AlertBar
元件傳遞到 AlertList
元件。接著,alertConfig
計算型 ref 回傳 style
和 direction
的值。alertConfig
將新的值傳遞給 Alert
元件以套用樣式。
<AlertBar
:config="config"
v-model:hasCloseButton="hasCloseButton"
v-model:style="style"
v-model:direction="direction"
/>
AlertBar
元件接收 config
prop。v-model:style="style"
。 將 AlertBar
元件的 style
ref 綁定到 AlertList
元件的 style
ref 。同樣地,v-model:direction="direction"
將 AlertBar
元件的 direction
ref 綁定到 AlertList
元件的 direction
ref。
樣式和方向的標籤及項目定義於 config
變數中。
<script lang="ts">
import AlertBar from './alert-bar.svelte';
import Alert from './alert.svelte';
const configs = $state(... same object...);
let hasCloseButton = $state(true);
let style = $state('color');
let direction = $state('horizontal');
</script>
與 hasCloseButton
類似,將 style
和 direction
變數新增到 AlertList
元件。
<AlertBar {configs}
bind:hasCloseButton={hasCloseButton}
bind:style={style}
bind:direction={direction}
/>
AlertBar
元件接收 config
prop 以填充下拉選單。AlertBar
使用 bind
語法將 style
和 direction
傳遞給 AlertList
元件。
{#each filteredNotification as alert (alert.type) }
<Alert {alert} {alertMessage} {notifyClosed} {hasCloseButton} {style} {direction} />
{/each}
將新的 prop 值 style
和 direction
傳遞給 Alert
元件。
樣式和方向的標籤及項目定義於 config
信號中。
import { ChangeDetectionStrategy, Component, computed, input, signal } from '@angular/core';
import { AlertComponent } from '../alert/alert.component';
import { AlertBarComponent } from '../alert-bar/alert-bar.component';
@Component({
selector: 'app-alert-list',
imports: [AlertComponent, AlertBarComponent],
template: `...inline template shown below ...`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertListComponent {
style = signal<string>('color');
direction = signal<string>('horizontal');
hasCloseButton = signal<boolean>(true);
config = signal({... same object ... });
alertConfig = computed(() => ({
hasCloseButton: this.hasCloseButton(),
style: this.style(),
direction: this.direction()
}));
}
與 hasCloseButton
類似,將 style
和 direction
信號新增到 AlertList
元件。alertConfig
計算型信號回傳 style
和 direction
信號的值。
<app-alert-bar
[config]="config()"
[(style)]="style"
[(direction)]="direction"
[(hasCloseButton)]="hasCloseButton"
/>
AlertBar
元件接收 config
輸入以填充下拉選單。AlertBar
使用香蕉盒語法 [(expression)]
,將 AlertBar
元件的 style
和 direction
models 綁定到 AlertList
元件的 style
和 direction
信號 (signals)。
[(style)]="style"
— 第一個 style
是 AlertBarComponent
的 style
model,第二個 style
是 AlertListComponent
的 style
信號 (signal)。
[(direction)]="direction"
— 第一個 direction
是 AlertBarComponent
的 direction
model,第二個 direction
是 AlertListComponent
的 direction
信號 (signal)。
type Props = {
alertConfig: {
hasCloseButton: boolean
style: string
direction: string
},
type: string
}
const { type, alertConfig } = defineProps<Props>()
在 Alert
元件的 Props
類型中,將 style
和 direction
新增到 alertConfig
屬性。
const alertColor = computed(() => ({
info: 'alert-info',
warning: 'alert-warning',
error: 'alert-error',
success: 'alert-success'
}[type]))
const alertStyle = computed(() => ({
color: '',
dash: 'alert-dash',
soft: 'alert-soft',
outline: 'alert-outline'
}[alertConfig.style]))
const alertDirection = computed(() => ({
horizontal: 'alert-horizontal',
vertical: 'alert-vertical',
}[alertConfig.direction]))
const alertClasses = computed(() => `alert ${alertColor.value} ${alertStyle.value} ${alertDirection.value}`)
建立 alertStyle
計算型 ref 用以推導樣式類別。建立 alertDirection
計算型 ref 用以推導方向類別。
alertClasses
計算型 ref 合併 Alert
元件的樣式類別 (style classes)。
<template>
<div role="alert" :class="alertClasses" v-if="!closed">
<!-- HTML button -->
</div>
</template>
alertClasses
將新樣式綁定到 class
屬性,以變更方向、邊框樣式及顏色。
type Props = {
hasCloseButton: boolean;
style: string;
direction: string;
}
const {
hasCloseButton,
direction,
style
}: Props = $props();
在 Alert
元件的 Props
類型中,新增 style
和 direction
屬性。
const alertColor = $derived.by(() => ({
info: 'alert-info',
success: 'alert-success',
warning: 'alert-warning',
error: 'alert-error',
}[alert.type]));
const alertDirection = $derived.by(() => ({
horizontal: 'alert-horizontal',
vertical: 'alert-vertical',
}[direction]));
const alertStyle = $derived.by(() => ({
color: '',
soft: 'alert-soft',
outline: 'alert-outline',
dash: 'alert-dash',
}[style]));
const alertClasses = $derived(`alert ${alertColor} ${alertDirection} ${alertStyle} mb-[0.75rem]`);
建立 alertStyle
衍生 rune 以衍生樣式類別 (style class)。建立 alertDirection
衍生 rune 以衍生方向類別 (direction class)。
{#if !closed}
<div role="alert" class={alertClasses}>
<!-- HTML button -->
</div>
{/if}
alertClasses
衍生 rune串接 Alert
元件的樣式類別,並將新的樣式綁定到 class
屬性,以變更方向、邊框樣式和顏色。
@Component({
selector: 'app-alert',
imports: [NgComponentOutlet, CloseIconComponent],
template: `... inline template ...`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AlertComponent {
type = input.required<AlertType>();
alertConfig = input.required<{
hasCloseButton: boolean
style: string
direction: string
}>();
alertColor = computed(() => {
return {
info: 'alert-info',
warning: 'alert-warning',
error: 'alert-error',
success: 'alert-success'
}[this.type()]
});
alertStyle = computed(() => {
return {
color: '',
dash: 'alert-dash',
soft: 'alert-soft',
outline: 'alert-outline'
}[this.alertConfig().style]
});
alertDirection = computed(() => {
return {
horizontal: 'alert-horizontal',
vertical: 'alert-vertical',
}[this.alertConfig().direction]
});
alertClasses = computed(() => `alert ${this.alertColor()} ${this.alertStyle()} ${this.alertDirection()}`);
}
將 style
和 direction
新增到 alertConfig
必填輸入信號中 (required input signal)。
建立 alertStyle
計算型信號以衍生樣式類別 (style class)。
建立 alertDirection
計算型信號以衍生方向類別 (direction class)。
alertClasses
計算型信號串接 Alert
元件的樣式類別。
@if (!closed()) {
<div role="alert" class="mb-[0.75rem]" [class]="alertClasses()">
<!-- HTML button -->
</div>
}
alertClasses
將新樣式綁定到 class
屬性,以變更方向、邊框樣式及顏色。
現在,使用者可以在 AlertBar
元件中選擇值,以顯示/隱藏關閉按鈕,並更改警示的邊框樣式、方向和顏色。