☕ NEW! 完成新手任務即可參加抽獎!LINE 星巴克禮券等你拿,名額有限!        🎉 推廣活動:邀請好友註冊 DevLearn,累積推薦抽 LINE 星巴克禮券! 活動詳情 →        🔥 活動期間 2026/4/1 - 5/31 |已有 0 人參加       
angular 初學

🧱 Angular 基礎:模板語法、資料綁定與元件

📌 元件(Component)= TypeScript + HTML + CSS

Angular 的核心概念是元件。每個元件由三個部分組成:

// counter.component.ts — TypeScript 邏輯
import { Component } from '@angular/core';

@Component({
  selector: 'app-counter',        // HTML 標籤名稱
  templateUrl: './counter.component.html',  // 模板檔案
  styleUrls: ['./counter.component.css']    // 樣式檔案
})
export class CounterComponent {
  count = 0;                       // 元件的資料(屬性)

  increment() {                    // 元件的方法
    this.count++;
  }

  decrement() {
    this.count--;
  }
}
<!-- counter.component.html — 模板 -->
<div class="counter">
  <h2>計數器</h2>
  <p>目前數值:{{ count }}</p>
  <button (click)="increment()">+1</button>
  <button (click)="decrement()">-1</button>
</div>

💡 注意@Component 是一個裝飾器(Decorator),這是 TypeScript 的功能,原生 JS 沒有。

📌 模板語法

插值(Interpolation){{ }}

<!-- 顯示元件屬性的值 -->
<h1>{{ title }}</h1>
<p>歡迎,{{ userName }}!你有 {{ messageCount }} 則訊息。</p>

<!-- 也可以放表達式 -->
<p>總價:{{ price * quantity }} 元</p>
<p>狀態:{{ isActive ? '啟用' : '停用' }}</p>

屬性綁定(Property Binding)[property]

<!-- 將元件屬性綁定到 HTML 屬性 -->
<img [src]="imageUrl" [alt]="imageDescription">
<button [disabled]="isLoading">送出</button>
<div [class.active]="isSelected">項目</div>
<div [style.color]="textColor">彩色文字</div>

事件綁定(Event Binding)(event)

<!-- 監聽 DOM 事件,觸發元件方法 -->
<button (click)="onSubmit()">送出</button>
<input (input)="onInputChange($event)">
<form (submit)="onFormSubmit($event)">
<div (mouseover)="onHover()" (mouseleave)="onLeave()">

雙向綁定(Two-way Binding)[(ngModel)]

// 需要先匯入 FormsModule
import { FormsModule } from '@angular/forms';

@Component({
  // ...
  imports: [FormsModule]  // Standalone component 直接匯入
})
export class SearchComponent {
  searchTerm = '';
}
<!-- 輸入框和資料自動雙向同步 -->
<input [(ngModel)]="searchTerm" placeholder="搜尋...">
<p>你正在搜尋:{{ searchTerm }}</p>
<!-- 當你打字時,searchTerm 自動更新;當程式改 searchTerm 時,輸入框也自動更新 -->

📌 結構指令

*ngIf — 條件顯示

<div *ngIf="isLoggedIn">
  歡迎回來,{{ userName }}!
</div>

<div *ngIf="items.length > 0; else emptyTemplate">
  共 {{ items.length }} 個項目
</div>
<ng-template #emptyTemplate>
  <p>目前沒有任何項目。</p>
</ng-template>

*ngFor — 迴圈渲染

<ul>
  <li *ngFor="let item of items; let i = index; trackBy: trackById">
    {{ i + 1 }}. {{ item.name }} - {{ item.price }} 元
  </li>
</ul>
// 元件中的 trackBy 函式(效能優化)
trackById(index: number, item: any): number {
  return item.id;
}

📌 @Input() 和 @Output() 裝飾器

@Input() — 父元件傳資料給子元件

// child.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<p>收到訊息:{{ message }}</p>`
})
export class ChildComponent {
  @Input() message = '';  // 從父元件接收資料
}
<!-- parent.component.html -->
<app-child [message]="'Hello from parent!'"></app-child>
<app-child [message]="dynamicMessage"></app-child>

@Output() — 子元件發送事件給父元件

// child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `<button (click)="sendMessage()">通知父元件</button>`
})
export class ChildComponent {
  @Output() notify = new EventEmitter<string>();

  sendMessage() {
    this.notify.emit('子元件說 Hello!');
  }
}
<!-- parent.component.html -->
<app-child (notify)="onChildNotify($event)"></app-child>
// parent.component.ts
onChildNotify(message: string) {
  console.log('收到子元件訊息:', message);
}

📌 完整範例:待辦清單

// todo.component.ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

interface Todo {
  id: number;
  text: string;
  done: boolean;
}

@Component({
  selector: 'app-todo',
  standalone: true,
  imports: [FormsModule, CommonModule],
  template: `
    <h2>待辦清單</h2>
    <div>
      <input [(ngModel)]="newTodo" placeholder="新增待辦..." (keyup.enter)="addTodo()">
      <button (click)="addTodo()" [disabled]="!newTodo.trim()">新增</button>
    </div>
    <ul>
      <li *ngFor="let todo of todos" [class.done]="todo.done">
        <input type="checkbox" [(ngModel)]="todo.done">
        {{ todo.text }}
        <button (click)="removeTodo(todo.id)">刪除</button>
      </li>
    </ul>
    <p>完成 {{ completedCount }} / {{ todos.length }} 項</p>
  `
})
export class TodoComponent {
  newTodo = '';
  todos: Todo[] = [];
  private nextId = 1;

  get completedCount(): number {
    return this.todos.filter(t => t.done).length;
  }

  addTodo() {
    if (this.newTodo.trim()) {
      this.todos.push({ id: this.nextId++, text: this.newTodo.trim(), done: false });
      this.newTodo = '';
    }
  }

  removeTodo(id: number) {
    this.todos = this.todos.filter(t => t.id !== id);
  }
}

🎯 注意:上面的 interface Todo 是 TypeScript 語法,原生 JS 沒有介面(interface)的概念。 TypeScript 的型別系統讓你在開發時就能發現錯誤,而不是在執行時才出問題。

📌 小結

  • 元件 = TypeScript(邏輯)+ HTML(模板)+ CSS(樣式)
  • 插值 {{ }} 顯示資料,[屬性] 綁定屬性,(事件) 監聽事件
  • [(ngModel)] 實現雙向綁定
  • *ngIf*ngFor 控制模板結構
  • @Input() 父傳子,@Output() 子傳父

💡 大家的想法 · 0

載入中...
💬 即時聊天室 🟢 0 人在線
😀 😎 🤓 💻 🎮 🎸 🔥
➕ 新問題
📋 我的工單
💬 LINE 社群
🔒
需要註冊才能使用此功能
註冊帳號即可解鎖測驗、遊戲、簽到、筆記下載等所有功能,完全免費!
免費註冊