本文章宗旨在于快速开始angular开发,或者快速了解angular开发注意事项的文章javascript
若是安装脚手架报错,强制清理npm缓存后从新安装css
当你下载好官方案列后,你可能对目录都不太熟悉,先不要将关注点放在这里,文章致力于如何快速上手一个angular项目。html
表达式中的上下文变量是由如下三种组成:java
当存在相同的表达式变量优先顺序:模板变量>>指令的上下文变量>>组件的成员变量npm
import { Component } from '@angular/core';
//my-app/src/app/app.component.ts
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
private data0:Number = 1121;
data1 = '<div>dddddd</div>';
data2 = {
aaa:222
};
data3(){
};
data4 = null;
data5 = undefined;
data6 = [1,2,3]
}
复制代码
<div>
<div>data0 :{{data0}}</div>
<div>data1 :{{data1}}</div>
<div>data2 :{{data2}}</div>
<div>data3 :{{data3}}</div>
<div>data4 :{{data4}}</div>
<div>data5 :{{data5}}</div>
<div>data6 :{{data6}}</div>
<div>data7 :{{data7}}</div>
</div>
<!-- data0 :1121 data1 :<div>dddddd</div> data2 :[object Object] data3 :function () { } data4 : data5 : data6 :1,2,3 data7 : -->
复制代码
先来看一个列子json
//html:<input type="text" value="a">
var outPutVal = function(){
console.log('getAttribute:',inO.getAttribute('value'));
console.log('inO.value:',inO.value);
}
window.onload = function(){
var inO = document.querySelect('input');
outPutVal(inO);
//getAttribute: a
//inO.value: a
document.onclick = function(){
//<input type="text" value="a"> 手动输入value为aaaaa后打印
outPutVal(inO);
//getAttribute: a
//inO.value: aaaaa
}
}
复制代码
以上原生js展现了HTML attribute 与 DOM property 的区别:缓存
angular中模板绑定是经过 property 和事件来工做的,而不是 attributebash
特殊的attribute 绑定app
[attr.aria-label]="actionName"
<td [attr.colspan]="1 + 1">
复制代码
指令分为三种:less
<div *ngIf="hero" class="name">{{hero.name}}</div>
-----------------------------------
<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
复制代码
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
({{i}}) {{hero.name}}
</div>
-----------------------------------
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
<div [class.odd]="odd">({{i}}) {{hero.name}}</div>
</ng-template>
复制代码
在渲染视图以前,Angular 会把 < ng-template > 及其包裹内容替换为一个注释
会将兄弟元素归为一组而且ng-template 会无反作用的包裹内部元素
无反作用是什么意思?(举个例子:破坏了html结构!):
<p>
I turned the corner
<span *ngIf="hero">
and saw {{hero.name}}. I waved
</span>
and continued on my way.
</p>
---------------------------
<p>
I turned the corner
<ng-container *ngIf="hero">
and saw {{hero.name}}. I waved
</ng-container>
and continued on my way.
</p>
复制代码
ng g c components/A 建立组件
复制代码
//a.component.ts
@Input()
inAttr:String;
private _name:String = '';
----------------------------------------------------
@Input()
set inAttr2(name:String){
this._name = name;
}
get inAttr2():String{
return this._name;
}
复制代码
//子组件中
@Output()
myEvent:EventEmitter<DataType> = new EventEmitter();
this.myEvent.emit(Data);
//父组件中
(myEvent)="myHandleEvent($event)"
myHandleEvent(Data:DataType){
}
复制代码
@ViewChild(ChildComponent)
private childComponent: ChildComponent;
ngAfterViewInit() {
setTimeout(() => this.seconds = () => this.childComponent.changeData, 0);
}
复制代码
ng g d myDirective/demo
复制代码
ElementRef:对视图中某个原生元素的包装器。
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appDemo]'
})
export class DemoDirective {
//构造函数要声明须要注入的元素 el: ElementRef。
constructor(private el:ElementRef) { }
// 注册事件
@HostListener('click')
show(){
console.log(this.el.nativeElement);
console.log(this.ss);
}
//指令参数,当参数名与指令名相同时,能够直接赋值给指令
@Input()
ss:String = 'aaa';
}
复制代码
<button appDemo [ss]="bbb">click me</button>
复制代码
TemplateRef:取得 < ng-template > 的内容
ViewContainerRef: 访问视图容器
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({ selector: '[appUnless]'})
export class UnlessDirective {
//第一次传入true时不执行任何if分支,提高性能
private hasView = false;
constructor(
private templateRef: TemplateRef<any>,
private viewContainer: ViewContainerRef) { }
@Input() set appUnless(condition: boolean) {
if (!condition && !this.hasView) {
//实列化一个试图,并把它插入到该容器中
this.viewContainer.createEmbeddedView(this.templateRef);
this.hasView = true;
} else if (condition && this.hasView) {
this.viewContainer.clear();
this.hasView = false;
}
}
}
复制代码
你能够将管道理解成将数据处理以后再显示的一种操做符,如:
<p>{{ birthday}}</p>
<p>{{ birthday | date }}</p>
<!--链式调用管道-->
<p>{{ birthday | date | uppercase}}</p>
复制代码
DatePipe、UpperCasePipe、LowerCasePipe、CurrencyPipe 和 PercentPipe.......
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
transform(value: number, exponent: string): number {
let exp = parseFloat(exponent);
return Math.pow(value, isNaN(exp) ? 1 : exp);
}
}
复制代码
Angular 只有在它检测到输入值发生了纯变动时才会执行纯管道。 纯变动是指对原始类型值(String、Number、Boolean、Symbol)的更改, 或者对对象引用(Date、Array、Function、Object)的更改。
Angular 会在每一个组件的变动检测周期中执行非纯管道。 非纯管道可能会被调用不少次,和每一个按键或每次鼠标移动同样频繁。
@Pipe({
name: 'flyingHeroesImpure',
pure: false
})
export class FlyingHeroesImpurePipe extends FlyingHeroesPipe {}
复制代码
依赖注入是实现控制反转的一种方式,将对象的创造权交出去,它的好处能够在实际开发中体现出来,如下会介绍它
依赖注入会让你用一种松耦合的方式去写代码,易于调试:
举个例子:
当你的服务分为开发版本与线上版本时,你可能须要两个不一样的服务devDataSevice与proDataSevice, 当你不使用依赖注入时,你须要在多个组件中new 出这两个对象来使用这两个服务,在线上环境与测试环境之间切换时,你须要更改多个组件中的代码,若是使用依赖注入的形式,你只须要更改提供器中的代码就能够更改全部组件中的服务,这大大下降了代码的耦合程度而且提升了可维护性。
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor() { }
}
复制代码
在哪里书写服务提供商:
在服务自己的 @Injectable() 装饰器中的 providedIn 的元数据选项
providedIn的值能够是'root'或者某个特定的NgModule
在 NgModule 的 @NgModule() 装饰器中的providers元数据选项
在组件的 @Component() 装饰器中providers元数据选项
在指令的 @Directive() 装饰器中providers元数据选项(元素级注入器)
providers中如何书写:
provider:[ProductService]
provider:[{provide:ProductService,useClass:ProductService}]
provider:[{provide:ProductService,useClass:AnotherProductService}]
provider:[{provide:ProductService,useFactory:(参数A)=>{return ob},deps:[参数A]}]
provider:[{provide:"IS_DEV_ENV",useValue:{isDev:true}}]
复制代码
在构造函数中注入:
construct(private productService:ProductService){...};
复制代码
<!--index.html中的head标签中加入<base href="/">来告诉路由该如何合成导航用的 URL-->
<base href="/">
复制代码
//app.module.ts
//导入路由核心模块
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{path:'**',component:AComponent}
];
@NgModule({
...
imports: [RouterModule.forRoot(routes)]
...
})
export class AppModule { }
复制代码
path "**"表示匹配全部
redirectTo "表示要转走的路径"
pathMatch "full"表示匹配程度
component 表示要显示的组件
data 数据传递
children:[] 子路由
canActivate:[PermissionGuard]
canDeactivate:[FocusGuard]
resolve:{Stock:StockResolve}
outlet 辅助路由
设置导航输出位置
<router-outlet></router-outlet> <!-- Routed components go here --> 复制代码
<a [routerLink]="['/path']" routerLinkActive="active">routelink</a>
<a [routerLink]="['./path']">routelink</a>
<a [routerLink]="['{outlets:{aux:'aaa'}}']">routelink</a> 辅助路由
http://localhost:4200/a(aux:aaa)
复制代码
Router可调用navigate与navigateByUrl()
//1.
[routerLink] = "['/path',1]"
//http://localhost:4200/path/1
// this.routeInfo.snapshot.queryParams
//2.
[routerLink]="['/b',1]" [queryParams]="{id:3}"
// http://localhost:4200/b/1?id=3
// this.routeInfo.snapshot.params
// 3.
{path:'a',component:AComponent,data:{id:666}}
//this.routeInfo.snapshot.queryParams
//this.routeInfo.snapshot.data
复制代码
export class PermissionGuard implements CanActivate{
canActivate(){
let hasPemission:boolean = Math.random() < 0.5;
return hasPemission;
}
}
复制代码
export class FocusGuard implements CanDeactivate<CComponent>{
canDeactivate(component:CComponent){
if(component.isFoucs){
return true;
}else {
return confirm('不关注一下嘛?');
}
}
}
复制代码
@Injectable()
export class StockResolve implements Resolve<Stock>{
constructor(
private route:Router
){}
resolve(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
return new Stock(1,'name');
}
}
复制代码
当 Angular的 组件或指令, 新建、更新和销毁时所触发的钩子函数
//1.constructor
//2.ngOnChanges
//3.ngOnInit
//4.ngDoCheck
//5.ngAfterContentInit
//6.ngAfterContentChecked
//7.ngAfterViewInit
//8.ngAfterViewChecked
复制代码
//1.ngOnChanges
//2.ngDoCheck
//3.ngAfterContentChecked
//4.ngAfterViewChecked
复制代码
//1.ngOnDestroy
// 在路由变动时改变
复制代码
1.子组件
<div>
<ng-content></ng-content>
</div>
2.父组件
<SComponent>
<!--在此写入的东西会投影到子组件-->
</SComponent>
复制代码
<form #myForm="ngForm" action="/regist" (ngSubmit)="createUser(myForm.value)" method="post">
<div>
<input ngModel name="a" type="text" required pattern="[a-zA-Z0-9]+">
</div>
<div>
second:<input ngModel #second="ngModel" name="a" type="text" required pattern="[a-zA-Z0-9]+">
</div>
<div>
<input ngModel name="b" type="text" required pattern="[a-zA-Z0-9]+">
</div>
<div ngModelGroup="tow">
<input ngModel name="a" type="text">
<input ngModel name="b" type="text">
</div>
<button type="submit">提交</button>
</form>
<div>
{{myForm.value | json}}
<br>
second值是:{{second.value}}
</div>
复制代码
private nickName = new FormControl('tom');
private passwordInfo = new FormGroup({
password: new FormControl(),
passwordConfirm:new FormControl()
});
private email = new FormArray([
new FormControl('a@a.com'),
new FormControl('b@b.com')
]);
复制代码
管理单体表单控件的值和有效性状态
管理一组 AbstractControl 实例的值和有效性状态
管理一组 AbstractControl 实例的值和有效性状态
<form [formGroup]="formModel" action="/regist" (Submit)="createUser()" method="post">
<input formControlName="nikname">
<ul formArrayName="emails">
<li *ngFor="let email of formModel.get('emails').controls;let i = index;">
<input [formControlName]="i">
</li>
</ul>
<button >增长email.....</button>
<input formControlName="emails">
<div formGroupName="passwordInfo">
<input formControlName="password">
<input formControlName="passwordConfirm">
</div>
</form>
复制代码
private formModel:FormGroup;
private fb:FormBuilder = new FormBuilder();
/*this.formModel = new FormGroup({ nikname:new FormControl(), emails:new FormArray([ new FormControl() ]), mobile:new FormControl(), passwordInfo:new FormGroup({ password:new FormControl(), passwordConfirm:new FormControl() }) });*/
this.formModel = this.fb.group({
nikname:[''],
emails:this.fb.array([
['']
]),
mobile:[''],
passwordInfo:this.fb.group({
password:[''],
passwordConfirm:['']
})
});
复制代码
//自定义校验器
xxx(param:AbstractControl):{[key:string]:any}{
return null;
}
// eg:
moblieValid(moblie:FormControl):any{
..........
// return null;表示成功
// return {...};不成功
}
//预约义校验器
Validators.required ......
nikname:["xxxx",[Validators.required,.....]]
.....................
let niknameValid;boolean = this.formModel.get('nikname').valid;
passwordInfo:this.fb.group({
password:[''],
passwordConfirm:['']
},{validator:this.passwordValidator}) //一次校验多个字段
复制代码
<div [hidden]="!formModel.hasError('required','nickname')"></div>
复制代码