装饰器
类级别
@Component()
@Directive()
@Pipe()
@Injectable()
@NgModule()
字段级别
@Input
@Output
NgModule
中小型项目中ngModule往往只有一个,但在大型应用中,往往多个功能相关的ngModule
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ],
entryComponents:[],
})
export class AppModule { }
declarations
声明此模块中拥有的组件。譬如包括:components, directives, and pipes。
exports
declarations 的子集。导出,供其他模块引用。
imports
声明需要引入的其他模块组件。
providers
定义service,可以定义在全局或者组件级别。
bootstrap
指定根视图,仅根视图可配置此项。或者配置此项的组件,即为根视图,用来承载其余组件。渲染dom时候,会替换index.html 中app-root对应的元素。
entryComponents
需要按类型进行引导或动态加载组件,则必须将其显式添加
常用模块 | 路径 | 描述 |
---|---|---|
BrowserModule | @angular/platform-browser | browser运行项目,必备之一,尤其web安全方面 |
CommonModule | @angular/common | 想使用NgIf,NgFor时,必须引入 |
FormsModule | @angular/forms | 想使用双向绑定NgModel时候 |
ReactiveFormsModule | @angular/forms | 想建立响应式应用 |
RouterModule | @angular/router | 想使用RouterLink,.forRoot()和.forChild() |
HttpClientModule | @angular/common/http | 想发起http请求时 |
其中,BrowserModule,CommonModule在app.module.ts中至少引入一个。
Component
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {}
selector -- 在html中使用的标签
模板
- 方法一:直接定义html内容template,适用于内容较少
@Component({
selector: 'lightswitch-comp',
template: `
<button (click)="clicked()">Click me!</button>
<span>{{message}}</span>`
})
export class LightswitchComponent {}
- 方法二:定义html文件路径templateUrl,适用于内容较多,扩展性好,还能发挥vscode等插件优势,推荐 。
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
providers -- 定义组件中依赖的其他业务逻辑
DI(Dependency Injection)- 依赖注入
创建服务
ng generate service xxx/xxxx
root级别, 整个应用都可用
@Injectable({
providedIn: 'root',
})
Module级别
import { Injectable } from '@angular/core';
import { UserModule } from './user.module';
@Injectable({
providedIn: UserModule,
})
export class UserService {
}
//or
import { NgModule } from '@angular/core';
import { UserService } from './user.service';
@NgModule({
providers: [UserService],
})
export class UserModule {
}
Component级别(常用于延迟加载服务)
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
服务注入过程
- 创建组件时候,check构造方法依赖参数
- 查询injector,是否存在对应的依赖服务
- 有则直接使用;没有,注入对应的服务,如果服务不存在,抛出异常
- 参数搜集完毕,调用构造方法,构造组件等实例
数据模型 -- js es6对象
数据显示
数值显示
{{}},进行属性绑定到html操作
<img src="{{imgSrc}}">
# or
<img [src]="imgSrc">
管道
{{ data | json | date:"MM/dd/yy" | uppercase }}
内置
- DatePipe
- UpperCasePipe
- LowerCasePipe,
- CurrencyPipe,
- PercentPipe
自定义管道
组件生命周期
onChanges
常用于父组件props传递数据,数据改变,组件视图修改
@Input、@Output
private _name:string ;
@Input
set name(val:string){
this._name = val;
}
get name():string {
return this._name;
}
private _address: string;
private _subject = new Subject<string>();
@Input
set address(val:string){
this._address = val;
this._subject.next(val);
}
get address():string {
return this._address;
}
此种set方法:
- 按照写的先后顺序,执行。
- 可以用于解决onChages依赖数据,可用subject,触发业务逻辑
onInit
组件初始化,可用于http请求发起,紧随ngChanges第一次调用后,触发。
ngDoCheck
Developer's custom change detection.
ngAfterContentInit
After component content initialized.
ngAfterContentChecked
After every check of component content
ngAfterViewInit
After a component's views are initialized,常用于dom操作,譬如绘图需要svg存在
ngAfterViewChecked
After every check of a component's views
onDestory
页面切换,指令销毁前,需要处理的业务逻辑,或者性能优化,避免内存泄漏
在以下情况中,可能会失效:
- Page Refresh
- Tab Close
- Browser Close
- Navigation Away From Page
# 推荐如下做法,确保OnDestroy执行
@HostListener('window:beforeunload')
async ngOnDestroy() {
if (this.myValueSub) {
this.myValueSub.unsubscribe();
}
}
angular rxjs subscribe,如果不unsubscirbe,会出现内存泄漏
父子组件通信
@Input
export class VoterComponent implements OnChanges {
@Input() name: string;
//changes监听name变化,
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
}
}
@Output
//output是一个事件,需要emit通知变动
export class VoterComponent implements OnChanges{
@Input() name: string;
@Output() voted = new EventEmitter<IDataChage>();
didVote = false;
vote(agreed: IDataChage) {
this.voted.emit(agreed);
this.didVote = true;
}
//changes监听name变化,
ngOnChanges(changes: SimpleChanges) {
// changes.prop contains the old and the new value...
}
}
//外层js接收如下:
dataChange(param:IDataChage):void{
const {agreed} = param;
}
Angular状态管理NgRx
component样式处理
Emulated模式
- 可以引用全局,不会对外暴露
- 默认值
- 采用该模式下,动态添加的组件,需要采用:host :ng-deep .xxx{ },生效样式
ShadowDom
- 存在兼容性问题
none
- 全局暴露
- 存在模块样式互相影响的负面
js代码处理
- 使用class="{{}}"
- 使用[ngClass]="{'ClazzA':true}"
- Render2
const dom = this.iconRef.nativeElement;
render2.addClass(dom,'clazzA')
指令
结构指令
影响界面元素布局
属性指令
影响界面元素属性、样式等
自定义指令
对数据进行转换处理,譬如 url的转义处理
Render2
主要用于替代Jquery,操作dom
HttpClient
Angular提供的模块HttpClient,发起Http请求,采用Observable模式,而非Promise
Rxjs
angular 响应式编程开发
单元测试
单元测试目的在于,提前发现,减少代码变动,业务功能的影响
编译模式
JIT (及时编译)
- ng build 和 ng serve 命令启动系统时, 默认采用
- 启动系统启动时候,编译template和转换ts为js,占用系统启动时间
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule);
AOT(ahead-of-time) 预编译
- ngc 命令触发
- 编译template和转换js,提前到构建时候
性能优化建议
lazy-loading
- 系统分割为多个模块,模块采取懒加载方式,有助于JIT模式下加快下载、启动速度
webpack-treeShaking
- 采用服务注入root级别,有利于webpack打包,treeshaking 无效code,减少包大小