你是否曾經感到困惑,不知道該選擇 React、Angular 還是 Vue.js 或是 jQuery?別擔心,這系列將為你深入解說這三個最受歡迎的前端框架,從學習曲線、性能、社區支持、適用場景等多個方面進行詳細解說,以幫助你做出明智的選擇。
Angular 是一個強大的前端框架,它的存在是為了讓前端開發變得更加容易且有組織性。它提供了一個強大的架構,幫助開發者構建互動性豐富的網頁應用程式。
Angular 是一個開源的前端框架,由 Google 開發和維護。它的主要目標是簡化前端開發,提供一個有組織的方法來構建 Web 應用程式。Angular 使用 TypeScript 作為主要的程式語言,這使得代碼更具可維護性和可擴展性。
Angular 不僅僅是一個 JavaScript 框架,它還包括了一個豐富的生態系統,如 Angular CLI、Angular Material 和 NgRx。Angular 的主要特點之一是它的組件化架構,讓開發者可以將應用程式拆分為多個獨立的組件,每個組件都有自己的視圖和邏輯,這使得代碼結構更清晰且易於維護。
Angular 提供了許多優點,這些優點使其成為許多人前端開發的首選框架:
Angular 開發需要使用 Node.js 和 npm,你可以從 Node.js 官方網站下載並安裝它。
Angular CLI(命令行界面)是一個強大的工具,可以幫助你快速建立和管理 Angular 專案。讓我們安裝它,在終端機中運行以下命令:
- npm install -g @angular/cli
這個指令將全局安裝 Angular CLI,讓你可以在任何地方使用它。安裝完成後,運行 ng --version
來確認一下,確保工具安裝完畢。
使用 Angular CLI,你可以輕鬆地創建一個嶄新的 Angular 應用程式。請在終端機中運行以下命令:
- ng new first-app
這個命令將帶領你回答一些問題,例如是否要包含 Angular 路由等。根據你的需求進行選擇。完成後,Angular CLI 將為你創建一個全新的專案,取名為 first-app
,並自動安裝所有必要的依賴項。
在 Angular 專案中,你將看到許多檔案和資料夾,它們具有不同的功能。以下是一些主要的檔案和資料夾:
src/
:這是你的應用程式代碼的主要目錄。src/app/
:這是你的應用程式的核心代碼,包括模組、服務和模組。angular.json
:這是 Angular 專案的配置文件,包含構建選項和全局配置。package.json
:這是你的專案依賴項的清單,包括 Angular 相關的套件。index.html
:你的應用程式的入口 HTML 文件。main.ts
:應用程式的主入口 TypeScript 文件。app.module.ts
:主要的應用程式模組,它定義了你的應用程式的模組和服務。現在,讓我們啟動開發伺服器,預覽你的 Angular 應用程式。在終端機中運行以下命令:
- ng serve
這將啟動開發伺服器並在本地瀏覽器中預覽你的應用程式。預設情況下,它將運行在 http://localhost:4200/
上。
Angular 的組件是前端應用程式的基本構建塊,想像你今天正在玩一組名為 Angular 的積木,每個組件都是你精心設計的元件,包含自己的工具和特殊功能,最後拼裝成一臺飛機等成果。這種模組化的設計方式使你的程式碼更有組織性,易於管理和維護。
讓我們以一個實例來解釋。假設你正在打造一個現代化的電子商務網站,內含商品列表、購物車和用戶註冊功能。你可以為每個功能建立獨立的組件,例如「Products」、「Cart」和「UserRegistration」。這樣的方式使你的程式碼更清晰,每個功能都有自己的專屬工作空間,使代碼更加易於維護、管理和測試。
現在,讓我們看一個實際的例子。假設你正在開發一個天氣的應用程式,你可以創建一個名為 weather
的組件,該組件負責顯示天氣信息。使用 Angular CLI,你可以運行以下命令創建組件:
- ng generate component weather
這將創建一個名為 weather
的組件,並生成相應的文件和資料夾。組件的模板、邏輯和樣式通常存放在一個文件夾中,並按照以下結構組織:
- weather/
- ├── weather.component.html
- ├── weather.component.ts
- └── weather.component.css
組件的模板是它的格局,就像一個店家的牆壁、管線。模板使用 HTML 編寫,但具有 Angular 的模板語法的優勢,讓你可以動態顯示數據,控制組件的外觀,以及處理事件。
讓我們以 weather
為例,假設我們想要顯示城市的名稱、溫度和天氣狀況。以下是一個簡單的模板:
- <h1>{{ city }} 天氣</h1>
- <p>溫度:{{ temperature }}°C</p>
- <p>天氣狀況:{{ condition }}</p>
在這個模板中,我們使用雙大括號 {{ }}
的語法,將組件中的變數動態顯示在模板上。這就是數據綁定的一個範例,我們將在稍後更詳細地討論。
每個組件都有自己的風格,就像是店家的裝潢、店面設計。通常,這些風格存放在 .css
或 .scss
檔案中。你可以在樣式檔案中定義樣式規則,然後將它們套用到組件的 HTML 元素上,以自訂組件的外觀。
舉個例子,如果我們想要為 weather
添加一些樣式,我們可以這樣做:
- .weather {
- background-color: #eee;
- padding: 0.5rem 1rem;
- border: 0.125rem solid #000;
- }
- <div class="weather">
- <h1>{{ city }} 天氣</h1>
- <p>溫度:{{ temperature }}°C</p>
- <p>天氣狀況:{{ condition }}</p>
- </div>
在這個範例中,我們為 .weather
類添加了一些樣式,你可以輕鬆地設計組件的外觀,使其符合你的應用程式風格。
在實際應用中,組件之間需要相互通信和共享數據。Angular 提供了多種方式來實現組件間的通信。
輸入和輸出屬性是一種常見的組件間通信方式。透過輸入屬性,你可以將資料傳遞給子組件,而透過輸出屬性,子組件則可以發送事件給父組件。
我們一樣用weather
的組件,寫一個 city-selector
來搭配做範例,當用戶在 city-selector
中選擇一個城市時,將該城市的名稱傳遞給 weather
並更新天氣信息。我們可以這樣做:
首先,讓我們創建 city-selector
組件。
city-selector.component.html
- <div>
- <input type="text" [(ngModel)]="selectedCity" placeholder="輸入城市名稱">
- <button (click)="onCitySelected()">選擇城市</button>
- </div>
將用戶輸入的城市名稱存儲在 selectedCity
變數中,並透過點擊觸發 selectCity
。使用 [(ngModel)]
來實現雙向數據綁定,後續還需配置 FormsModule
,以支援雙向數據綁定。CitySelectorComponent但接下來,我們先在 city-selector.component.ts
中實現相關的邏輯。city-selector.component.ts
- import { Component, Output, EventEmitter } from "@angular/core";
- @Component({
- selector: "app-city-selector",
- templateUrl: "./city-selector.component.html",
- styleUrls: ["./city-selector.component.css"]
- })
- export class CitySelectorComponent {
- @Output() citySelected: EventEmitter<string> = new EventEmitter<string>();
- selectedCity: string = ""; // 使用 ngModel 來綁定輸入框的值
- onCitySelected() {
- if (this.selectedCity) {
- this.citySelected.emit(this.selectedCity); // 發送選擇的城市名稱到父組件
- };
- };
- };
接下來,讓我們使用 weather
組件來接收這個城市名稱並更新天氣信息。weather.component.ts
typescript
weather
組件中,我們設置了 city
、temperature
和 condition
屬性,用於顯示城市名稱、溫度和天氣狀況。然後,我們創建了一個 onCitySelected
方法,用於接收從 city-selector
組件傳遞過來的城市名稱,並根據城市名稱更新天氣信息。weather.component.html
模板中,你可以使用這些屬性來顯示天氣信息。weather.component.html
- <div class="weather">
- <h1>{{ city }} 天氣</h1>
- <p>溫度:{{ temperature }}°C</p>
- <p>天氣狀況:{{ condition }}</p>
- </div>
最後我們在主要的應用程式模組 app.module.ts
中導入 FormsModule
並配置 CitySelectorComponent
與 WeatherComponent
。 app.module.ts
- // app.module.ts
- import { NgModule } from "@angular/core";
- import { BrowserModule } from "@angular/platform-browser";
- import { FormsModule } from "@angular/forms"; // 導入 FormsModule
- import { AppComponent } from "./app.component";
- import { CitySelectorComponent } from "./city-selector.component"; // 確保路徑正確
- import { WeatherComponent } from "./weather.component"; // 確保路徑正確
- @NgModule({
- imports: [
- BrowserModule,
- FormsModule, // 添加 FormsModule 到 imports
- ],
- declarations: [
- AppComponent,
- CitySelectorComponent,
- WeatherComponent,
- ],
- bootstrap: [AppComponent],
- })
- export class AppModule { };
app.component.html
- <app-city-selector (citySelected)="onCitySelected($event)"></app-city-selector>
- <app-weather [city]="selectedCity"></app-weather>
這樣,當用戶在搜索框中輸入城市名稱時,它將被傳遞給 WeatherComponent
,並顯示相應的天氣信息。Angular 組件的生命週期是開發過程中的關鍵,因為它涵蓋了組件從創建到銷毀的整個過程。這些生命週期允許你在不同階段執行自定義邏輯,以確保你的應用程序按照預期運行。
Angular 提供了一系列的生命週期,如 ngOnInit
、ngOnChanges
、ngOnDestroy
等,它們允許你在特定階段執行自定義邏輯。如果你需要在組件初始化時執行某些代碼,你可以使用 ngOnInit
:
- ngOnInit() {
- this.fetchWeatherInfo(this.city);
- }
在這個範例中,我們使用了一個更具描述性的函數名 fetchWeatherInfo
來代表獲取天氣信息的操作,這樣可以讓代碼更易讀。請確保在 ngOnInit
中執行的操作是輕量級的,以避免影響組件的性能。
ngOnChanges
通常用於監視組件的輸入屬性變化,但是在使用之前,你應該先檢查新值和舊值是否真的有變化,以避免不必要的操作。這樣可以提高性能並減少不必要的重繪。
- ngOnChanges(changes: SimpleChanges) {
- if (changes.city && changes.city.currentValue !== changes.city.previousValue) {
- this.fetchWeatherInfo(this.city);
- }
- }
在這個範例中,我們通過比較 currentValue
和 previousValue
來確保只有在 city
真正發生變化時才執行 fetchWeatherInfo
。
最後,在組件銷毀時進行資源的清理工作,以避免內存泄漏。你可以使用 ngOnDestroy
來實現這一點,例如取消訂閱觀察者或清理訂閱的資源。
- ngOnDestroy() {
- this.subscription.unsubscribe();
- }
單向數據綁定是一種將數據從組件傳遞到模板的方式,但不允許模板對數據進行修改。這種綁定方式通常用於將組件中的數據呈現在用戶界面上,這樣用戶就可以查看相關數據。舉例來說,如果我們有一個顯示用戶名的變數,我們可以在模板中這樣使用:
- <p>{{ username }}</p>
這是一個更強大的綁定方式,它不僅允許數據從組件傳遞到模板,還允許模板中的變更即時回傳到組件。這在處理表單元素等需要用戶輸入的情境中非常實用。例如,如果我們有一個用戶名的輸入框,我們可以使用[(ngModel)]實現雙向綁定:
- <input [(ngModel)]="username">
現在,當用戶在輸入框中輸入用戶名時,username
變數的值將自動更新,同時如果在組件中修改了 username
的值,輸入框中的內容也會同步更新。
ps. 需要在模塊中導入 FormsModule
,並在組件中引入 FormsModule
以使用雙向數據綁定。且需要確保模型屬性與模板中綁定的屬性名稱匹配,否則綁定將不起作用。
在我們之前的範例中,我們已經看到了插值表達式的使用,它允許我們將組件中的變數值顯示在模板中。另一種方式是使用屬性綁定,它允許我們將組件的屬性值綁定到模板元素的屬性上。
插值表達式使用雙花括號 {{ }}
來包圍組件變數,將其值插入到模板中。這對於將數據呈現在 HTML 中非常方便。例如:
- <p>{{ message }}</p>
屬性綁定使用方括號 [ ]
來指定要綁定的 HTML 元素屬性,然後將組件的屬性值賦給它。這對於動態設置 HTML 元素的屬性非常有用。例如:
- <img [src]="imageUrl">
另一個常見的用例是屬性綁定到元素的 disabled
屬性,這在按鈕等元素中非常有用:
- <button [disabled]="isDisabled">點擊</button>
在這個例子中,isDisabled
變數的值決定了按鈕是否處於禁用狀態。當 isDisabled
為 true
時,按鈕將被禁用。
在Angular中,事件處理是實現與用戶互動的重要部分。你可以透過事件綁定來捕獲和處理各種用戶交互事件,例如點擊、輸入、滑鼠事件等。以下是更詳細的說明和範例:
事件綁定允許你將模板中的事件(如點擊)與組件中的方法關聯起來,以便在事件發生時執行特定的操作。你可以使用括號 ()
來指定事件,並在括號內放入事件名稱,然後指定要調用的組件方法。舉例如下:
- <button (click)="onButtonClick()">點擊我</button>
- onButtonClick() {
- this.fetchWeatherInfo(this.city);
- }
這樣,當用戶點擊按鈕時,onButtonClick 方法將被觸發。
有時候,你可能需要獲取有關事件的更多信息,例如滑鼠事件的坐標或鍵盤事件的按鍵信息。你可以通過將 $event
傳遞給組件方法來獲取事件對象。舉例來說:
- <input (keyup)="onKeyUp($event)">
- onKeyUp(event: KeyboardEvent) {
- console.log(event.keyCode);
- }
這樣,你可以獲取有關按鍵事件的詳細信息並做出相應的處理。
路由是指導航的基礎,它允許你在不同的視圖之間切換,就像在單頁應用程式中一樣。在 Angular 中,你可以使用 RouterModule
來設置路由。讓我們假設你正在建立一個簡單的博客應用程式,其中包含主頁、文章列表和文章詳細頁面。
你需要在應用程式的根模塊中配置路由器:
- // app.module.ts
- import { NgModule } from "@angular/core";
- import { RouterModule, Routes } from "@angular/router";
- import { HomeComponent } from "./home.component";
- import { BlogListComponent } from "./blog-list.component";
- import { BlogSingleComponent } from "./blog-single.component";
- const routes: Routes = [
- { path: "", component: HomeComponent },
- { path: "blog", component: BlogListComponent },
- { path: "blog/:id", component: BlogSingleComponent },
- ];
- @NgModule({
- imports: [RouterModule.forRoot(routes)],
- exports: [RouterModule],
- })
- export class AppModule {}
在這個例子中,我們定義了三個路由:主頁、文章列表頁面 blog
和文章詳細頁面 blog/:id
。這些路由與相應的組件相關聯。
接下來,你需要在應用程式的模板中添加一個 <router-outlet></router-outlet>
標記,這個標記將用來顯示不同路由下的內容:
- <nav>
- <a routerLink="/">主頁</a>
- <a routerLink="/blog">文章列表</a>
- </nav>
- <router-outlet></router-outlet>
你已經設置了基本的路由結構。當用戶點擊頁面上的鏈接時,應用程式將根據路由的定義顯示相應的內容。
你可能希望在一個路由下設置子路由,來實現更複雜的導航結構。假設你的博客應用程式需要一個用於編輯文章的功能,你可以使用子路由來實現:
- const routes: Routes = [
- { path: "", component: HomeComponent },
- { path: "blog", component: BlogListComponent },
- {
- path: "blog/:id",
- component: BlogSingleComponent,
- children: [
- { path: "edit", component: BlogEditComponent },
- ],
- },
- ];
當用戶訪問 articles/1/edit
時,將顯示 BlogEditComponent
。
路由守衛允許你在導航到某個路由前執行一些操作。這對於驗證用戶、保護特定頁面或執行特定任務非常有用。在 Angular 中,有四種主要的路由守衛:
假設你希望確保只有登入的用戶才能訪問編輯文章頁面:
auth.service.ts
- import { Injectable } from "@angular/core";
- @Injectable({
- providedIn: "root",
- })
- export class AuthService {
- private isAuthenticated: boolean = false;
- login() {
- this.isAuthenticated = true;
- }
- logout() {
- this.isAuthenticated = false;
- }
- isAuthenticatedUser(): boolean {
- return this.isAuthenticated;
- }
- }
在這個範例中,AuthService
服務模擬了 login
、logout
和 isAuthenticatedUser
身份驗證操作的方法。auth.guard.ts
- import { Injectable } from "@angular/core";
- import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from "@angular/router";
- import { Observable } from "rxjs";
- import { AuthService } from "./auth.service"; // 導入AuthService
- @Injectable({
- providedIn: "root",
- })
- export class AuthGuard implements CanActivate {
- constructor(private authService: AuthService, private router: Router) {}
- canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
- if (this.authService.isAuthenticatedUser()) {
- return true;
- }
- else {
- // 如果未登入,重定向到登入頁面
- this.router.navigate(["/login"]);
- return false;
- }
- }
- }
在這個範例中,AuthGuard
檢查用戶是否已登入,如果已登入,則允許訪問路由,否則將用戶重定向到登入頁面。接下來,我們可以在路由配置中使用這個守衛。假設我們有一個需要身份驗證的私人頁面,我們可以這樣設置它:app.module.ts
- const routes: Routes = [
- {
- path: "articles/:id/edit",
- component: BlogEditComponent,
- canActivate: [AuthGuard],
- },
- ];
當用戶訪問 articles/1/edit
頁面時,將首先觸發 AuthGuard
,並檢查是否允許訪問。懶加載是一種優化技術,它允許你將應用程式按需分割成多個模塊,以降低初始加載時間。在 Angular 中,你可以使用懒加载模塊來實現這一目標。先建立一個懒加載模塊:
blog-list.module.ts
- //
- import { NgModule } from "@angular/core";
- import { RouterModule, Routes } from "@angular/router";
- import { BlogListComponent } from "./blog-list.component";
- const routes: Routes = [
- { path: "", component: BlogListComponent },
- ];
- @NgModule({
- imports: [RouterModule.forChild(routes)],
- exports: [RouterModule],
- })
- export class BlogListModule {}
接著,在路由配置中使用 canLoad
守衛來實現懶加載:app.module.ts
- const routes: Routes = [
- {
- path: "blog",
- loadChildren: () => import("./blog-list.module").then((m) => m.BlogListModule),
- canLoad: [AuthGuard],
- },
- ];
這將使 BlogListModule
在用戶首次訪問 /blog
頁面時才被加載。模板驅動表單是一種較簡單的方式來處理表單,它的主要思想是將表單的狀態和行為與模板相關聯。在這種方法中,你可以使用 Angular 模板語法來建立表單,然後通過模板變數來訪問和操作表單控件。以下是一個簡單的模板驅動登入表單:
- <form #loginForm="ngForm" (ngSubmit)="onSubmit()">
- <label for="username">名稱:</label>
- <input type="text" id="username" name="username" [(ngModel)]="user.username" required>
- <label for="password">密碼:</label>
- <input type="password" id="password" name="password" [(ngModel)]="user.password" required>
- <button type="submit">登入</button>
- </form>
在這個例子中,我們使用 ngForm
指令來建立表單,並使用 [(ngModel)] 雙向數據綁定將表單控件與組件中的屬性關聯起來。當用戶提交表單時,我們呼叫 onSubmit
方法來處理表單數據。
模板驅動表單的優勢在於簡單易上手,特別適用於簡單的表單。但對於複雜的表單,響應式表單可能更適合。
響應式表單是一種更強大和靈活的方式來處理表單。它使用 RxJS 庫來建立表單控件的可觀察對象,這些對象允許你更細粒度地控制表單的狀態和行為。以下是一個簡單的響應式登入表單範例:
- import { Component } from "@angular/core";
- import { FormBuilder, FormGroup, Validators } from "@angular/forms";
- @Component({
- selector: "app-login",
- template: `
- <form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
- <label for="username">名稱:</label>
- <input type="text" id="username" formControlName="username">
- <label for="password">密碼:</label>
- <input type="password" id="password" formControlName="password">
- <button type="submit">登入</button>
- </form>
- `,
- })
- export class LoginComponent {
- loginForm: FormGroup;
- constructor(private fb: FormBuilder) {
- this.loginForm = fb.group({
- username: ["", Validators.required],
- password: ["", Validators.required],
- });
- }
- onSubmit() {
- if (this.loginForm.valid) {
- // 表單驗證通過,處理登入
- }
- }
- }
在這個範例中,我們使用 FormBuilder
創建了一個包含驗證規則的 FormGroup
,並通過 formControlName
將表單控件綁定到模板中。當表單驗證通過時,我們執行登入操作。
表單驗證是確保用戶輸入的數據符合預期的一個關鍵部分。不論你使用模板驅動表單還是響應式表單,Angular 都提供了豐富的驗證機制來幫助你實現這一目標。假設用戶名和密碼字段都是必填的。在模板驅動表單中,你可以添加 required
屬性:
- <input type="text" id="username" name="username" [(ngModel)]="user.username" required>
- <input type="password" id="password" name="password" [(ngModel)]="user.password" required>
在響應式表單中,你則是這樣做:
- this.loginForm = fb.group({
- username: ["", [Validators.required]],
- password: ["", [Validators.required]],
- });
當用戶未填寫必填字段時,Angular 將自動顯示錯誤消息。你還可以自定義驗證器來滿足特定需求,例如驗證用戶名是否唯一或密碼是否符合一定的複雜性要求。
在錯誤處理方面,Angular 允許你輕鬆地檢測和處理表單中的錯誤。你可以通過以下方式檢測特定控件的錯誤:
- const usernameControl = this.loginForm.get("username");
- if (usernameControl.hasError("required")) {
- // 用戶名是必填的,執行相應的處理
- }
Angular 提供了 HttpClient
模組,用於發送 HTTP 請求。使用它,你可以輕鬆地執行 GET
、POST
、PUT
、DELETE
等各種類型的請求。以下提供一個範例:
- import { HttpClient } from "@angular/common/http";
- constructor(private http: HttpClient) {}
- getData() {
- return this.http.get("/api/data");
- }
- postData(data: any) {
- return this.http.post("/api/data", data);
- }
在這個範例中,我們定義了 getData
和 postData
方法,分別向後端發送 GET
和 POST
請求。
在現實應用中,HTTP 請求可能會遇到錯誤,例如服務器錯誤或網絡問題。為了提供更好的用戶體驗,我們需要妥善處理這些錯誤。
- getData() {
- return this.http.get("/api/data").pipe(
- catchError((error: any) => {
- // 在這裡處理錯誤,例如顯示錯誤消息或記錄錯誤
- return throwError("錯誤");
- })
- );
- }
在這個範例中,我們使用 catchError
來執行相應的處理。根據實際需求進行錯誤處理。
測試是確保應用程式穩定性的關鍵部分。對於 HTTP 請求,你可以使用 Angular 的測試工具來撰寫單元測試和集成測試。假設我們有一個 DataService
需要測試:
data.service.ts
- import { Injectable } from "@angular/core";
- import { HttpClient } from "@angular/common/http";
- import { Observable } from "rxjs";
- @Injectable({
- providedIn: "root",
- })
- export class DataService {
- constructor(private http: HttpClient) {}
- getData(): Observable<any> {
- return this.http.get("/api/data");
- }
- }
接下來編寫一個單元測試,來測試 DataService
的 getData
。data.service.spec.ts
- import { TestBed, inject } from "@angular/core/testing";
- import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
- import { DataService } from "./data.service";
- describe("DataService", () => {
- let service: DataService;
- let httpMock: HttpTestingController;
- beforeEach(() => {
- TestBed.configureTestingModule({
- imports: [HttpClientTestingModule],
- providers: [DataService],
- });
- service = TestBed.inject(DataService);
- httpMock = TestBed.inject(HttpTestingController);
- });
- it("應該被建立", () => {
- expect(service).toBeTruthy(); // 確保 service 變數不是 null 或 undefined
- });
- it("應該透過 GET 從 API 獲取數據", () => {
- const testData = { message: "這是一個測試" };
- service.getData().subscribe((data) => {
- expect(data).toEqual(testData); // 驗證數據是否如預期
- });
- const req = httpMock.expectOne("/api/data");
- expect(req.request.method).toEqual("GET"); // 方法是 GET
- req.flush(testData); // 模擬 HTTP 請求
- httpMock.verify();
- });
- afterEach(() => {
- httpMock.verify();
- });
- });
Angular 的官方文檔是一個非常棒的學習資源,它包括了導覽、教程和詳細的API參考。通過閱讀文檔和完成官方教程,你可以快速地瞭解 Angular 的基本概念和使用方法。