Angular是目前热门的前端开发框架之一。通过一段时间的实践操作,再次回头梳理,对Angular有了更系统的认识。
关联技术
- TypeScript:JavaScript的超集,为JavaScript引入了类(class)的概念。
- RxJS:JavaScript的一个响应式扩展库(Reactive Extensions Library for JavaScript),主要使用了其中一个关键类Observable(可观察对象),以及一些相关的函数如of()函数等。
- Node.js 和 npm:开发环境。
Angular 和 Angular CLI
Angular是一个库,里面包含了很多模块来简化开发;Angular CLI是一个辅助脚手架工具,本质是一个命令行工具,通过不同命令执行相应的操作来简化项目开发的流程,如:创建项目、添加文件、执行开发任务如测试、打包和发布。
通常项目目录结构如下:

组成
Angular主要由类文件组成,一个类文件大体包含以下几个部分:
- 引入行:包含了需要引入的文件
- 装饰器函数:@后跟一个单词表示该文件的作用,如@Component表示组件,@NgModule表示模块,@Injectable表示服务。参数对象描述了元数据,为Angular如何处理文件给出了指示。
- 导出类:类中通常包含变量(属性)声明、构造函数、生命周期钩子(最常使用ngOnInit ,Angular 在创建完组件后很快就会调用 ngOnInit。这里是放置初始化逻辑的好地方。
)、方法。
Angular根据文件的作用不同可以分为以下几类:
组件:Component
最基础的部分,是页面的组成单位。一个组件包含三个主要文件:类文件(.ts)、HTML文件(.html)、样式文件(.css)。
- HTML
支持模板语法,使用{{变量名}}的形式获取ts文件中定义的变量。
单向绑定:<img [src]="url">
双向绑定:<input [(ngModel)]="value">
事件绑定:<button (click)="fn()"></button>
class绑定:[class.some-css-class]="some-condition" - 组件交互:
- 父 -> 子
父:<app-hero-detail [hero]="selectedHero"></app-hero-detail>
子:@Input() hero: Hero; // hero 属性必须是一个带有 @Input() 装饰器的输入属性,因为外部的 HeroesComponent 组件将会绑定到它。
// heroes.component.ts
import { Component, OnInit } from '@angular/core';
import { HEROES } from '../mock-heroes';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
heroes = HEROES; // 直接引入一个类,直接复制给变量
constructor(private heroService: HeroService) { } // 注入服务
ngOnInit() {
}
}
组件模块:NgModule
模块是用来声明组件的,并为组件引入所需的其他模块。
//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';
@NgModule({
declarations: [ // 声明组件
AppComponent,
HeroesComponent
],
imports: [ // 引入外部模块
BrowserModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
路由模块:NgModule
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HeroesComponent } from './heroes/heroes.component';
const routes: Routes = [ // 定义路由
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' }, // 这个路由会把一个与空路径“完全匹配”的 URL 重定向到路径为 '/dashboard' 的路由。
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent }, // path 中的冒号(:)表示 :id 是一个占位符,它表示某个特定英雄的 id。
{ path: 'heroes', component: HeroesComponent }
];
// path:一个用于匹配浏览器地址栏中 URL 的字符串。
// component:当导航到此路由时,路由器应该创建哪个组件。
// 路由出口:<router-outlet></router-outlet>
// 导航:<a routerLink="/heroes">Heroes</a>
// <a *ngFor="let hero of heroes" routerLink="/detail/{{hero.id}}">
@NgModule({
imports: [ RouterModule.forRoot(routes) ], // 初始化路由器
exports: [ RouterModule ]
})
export class AppRoutingModule { }
服务:Injectable(注射剂)
服务是在多个“互相不知道”的类之间共享信息的好办法。不要使用 new 来创建此服务,而要依靠 Angular 的依赖注入机制把它注入到 HeroesComponent 的构造函数中。HttpClient.get() 会返回 Observable。
// hero.service.ts
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root', // 注射器,值为注射范围?
})
export class HeroService {
constructor() { }
getHeroes(): Observable<Hero[]> {
return of(HEROES);
}
}
组件订阅服务:
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
普通类/接口/数据模型
// hero.ts
export class Hero {
id: number;
name: string;
}
开发风格
- 按模块名字的字母顺排列导入行
- 在解构表达式中按字母顺序排列导入的东西
- 在第三方导入和应用导入之间留一个空行
未完待续... ...
网友评论