摘要
本文主要讲述了:
- 新建组件
- 使用组件
- 父组件向子组件传递数据
- 子组件向父组件发射自定义事件
- 单向数据流
- 插槽
- 在根模块中使用子模块中的组件
正文
注意:
- 任何一个组件都必须隶属于一个领域模块
- 想要在根模块中使用子模块中的组件,必须让对应的子模块先输出对应的组件,然后在根模块内引用对应的子模块
新建组件
示例:
- 在
src/app/
目录内创建名为components/job
的目录
- 在
src/app/components/job/
目录内创建job.component.css
、job.component.html
、job.component.ts
、job.component.spec.ts
- 在
src/app.module.ts
中引用JobComponent
1 2 3
| #!/usr/bin/env bash
ng generate component components/job
|
使用组件
- 一个组件的模板文件中,可以有多个顶层元素
示例:
my-angular/src/app/app.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { FooComponent } from './pages/foo/foo.component'; import { BarComponent } from './pages/bar/bar.component';
import { RegisterModule } from './modules/register/register.module';
import { SalaryPipe } from './pipes/salary.pipe'; import { IsVipPipe } from './pipes/is-vip.pipe';
import { LoginFormComponent } from './components/login-form/login-form.component'; import { JobComponent } from './components/job/job.component';
@NgModule({ declarations: [ AppComponent, FooComponent, BarComponent, SalaryPipe, IsVipPipe, LoginFormComponent, JobComponent, ], imports: [ BrowserModule, FormsModule, ReactiveFormsModule, HttpClientModule, AppRoutingModule, RegisterModule, ], providers: [], bootstrap: [AppComponent], }) export class AppModule {}
|
my-angular/src/app/app.component.html
1 2 3
| <div *ngFor="let item of jobList; trackBy: jobTrackBy"> <app-job></app-job> </div>
|
my-angular/src/app/app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| import { Component } from '@angular/core'; import { Job } from './types/Job';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { jobList: Job[] = [ { jobId: 1, jobName: '会计', salary: 1000, companyName: 'A有限责任公司', isVip: 1, }, { jobId: 2, jobName: '销售', salary: 2000, companyName: 'B有限责任公司', isVip: 0, }, { jobId: 3, jobName: '主管', salary: 3000, companyName: 'B有限责任公司', isVip: 0, }, ];
jobTrackBy(index: number, item: Job) { return item.jobId; } }
|
父组件向子组件传递数据
使用Input()
装饰器来装饰属性
示例:
my-angular/src/app/app.component.html
1 2 3
| <div *ngFor="let item of jobList; trackBy: jobTrackBy"> <app-job [job]="item"></app-job> </div>
|
my-angular/src/app/components/job/job.component.html
1 2 3 4 5 6
| <div> <div>{{ job.jobId }}</div> <div>{{ job.jobName }}</div> <div>{{ job.salary }}</div> <div>{{ job.companyName }}</div> </div>
|
my-angular/src/app/components/job/job.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import { Component, OnInit, Input } from '@angular/core'; import { Job } from 'src/app/types/Job';
@Component({ selector: 'app-job', templateUrl: './job.component.html', styleUrls: ['./job.component.css'], }) export class JobComponent implements OnInit { @Input() job: Job = { jobId: 0, jobName: '', salary: 0, companyName: '', };
constructor() {}
ngOnInit(): void {} }
|
子组件向父组件发射自定义事件
使用Output()
装饰器来装饰自定义事件
示例:
my-angular/src/app/app.component.html
1 2 3
| <div *ngFor="let item of jobList; trackBy: jobTrackBy"> <app-job [job]="item" (clickEvent)="onClick($event)"></app-job> </div>
|
my-angular/src/app/app.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import { Component } from '@angular/core'; import { Job } from './types/Job';
@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { jobList: Job[] = [ { jobId: 1, jobName: '会计', salary: 1000, companyName: 'A有限责任公司', isVip: 1, }, { jobId: 2, jobName: '销售', salary: 2000, companyName: 'B有限责任公司', isVip: 0, }, { jobId: 3, jobName: '主管', salary: 3000, companyName: 'B有限责任公司', isVip: 0, }, ];
jobTrackBy(index: number, item: Job) { return item.jobId; }
onClick(jobId: number) { console.log(jobId); } }
|
my-angular/src/app/components/job/job.component.html
1 2 3 4 5 6
| <div (click)="onClick()"> <div>{{ job.jobId }}</div> <div>{{ job.jobName }}</div> <div>{{ job.salary }}</div> <div>{{ job.companyName }}</div> </div>
|
my-angular/src/app/components/job/job.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; import { Job } from 'src/app/types/Job';
@Component({ selector: 'app-job', templateUrl: './job.component.html', styleUrls: ['./job.component.css'], }) export class JobComponent implements OnInit { @Input() job: Job = { jobId: 0, jobName: '', salary: 0, companyName: '', };
@Output() clickEvent = new EventEmitter<number>();
onClick() { this.clickEvent.emit(this.job.jobId); }
constructor() {}
ngOnInit(): void {} }
|
单向数据流
子组件不能直接变更由父组件传入的数据,而是应该向父组件发射自定义事件,通知父组件变更
自始至终,数据都保存在父组件中,数据变更也发生在父组件中
若:
- 父组件传递给子组件的属性名为
x
- 子组件发射给父组件的自定义事件名为
xChange
则:
在父组件的模板文件中,子组件的属性绑定和事件监听可以写成[(x)]
的形式
插槽
示例:
my-angular/src/app/app.component.html
1 2 3 4
| <app-login-form> <div header>hello, jsweibo</div> <div footer>bye, jsweibo</div> </app-login-form>
|
my-angular/src/app/components/login-form/login-form.component.html
1 2 3 4 5 6 7 8 9
| <div> <div class="form-header"> <ng-content select="[header]"></ng-content> </div> <div class="form-body"></div> <div class="form-footer"> <ng-content select="[footer]"></ng-content> </div> </div>
|
在根模块中使用子模块中的组件
示例:
my-angular/src/app/modules/register/register.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common';
import { RegisterRoutingModule } from './register-routing.module'; import { ResetPasswordComponent } from './pages/reset-password/reset-password.component'; import { UserAgreementComponent } from './components/user-agreement/user-agreement.component';
@NgModule({ declarations: [ResetPasswordComponent, UserAgreementComponent], imports: [CommonModule, RegisterRoutingModule], exports: [UserAgreementComponent], }) export class RegisterModule {}
|
my-angular/src/app/app.component.html
1
| <app-user-agreement></app-user-agreement>
|
参考资料
本文对你有帮助?请支持我