angula7.0.0使用指南

环境搭建
脚手架安装:npm i -g @angular/cli
新建项目:ng new my-app
如果安装脚手架报错,强制清理npm缓存后重新安装

组件与模板
当你下载好官方案列后,你可能对目录都不太熟悉,不过不用关心

理解模板表达式上下文
组建实列就是模板表达式的上下文对象(Expression context)

表达式中的上下文变量是由 模板变量 、 指令的上下文变量(如果有)和 组件的成员变量 叠加而成的。
当存在相同的表达式变量优先顺序:模板变量、指令的上下文变量、组件的成员变量

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>

理解HTML attribute 与 DOM property
先来看一个列子

    //html:<input type="text" value="a">
    var outPutVal = function(inO){
        console.log('getAttribute:',inO.getAttribute('value'));
        console.log('inO.value',inO.value);
    }
    window.onload = function(){
        var inO = document.querySelector('input');
        //<input type="text" value="a"> 初始化value后打印
        outPutVal(inO);
        //getAttribute: a
        //test.html:14 inO.value a
        document.onclick = function(){
            //<input type="text" value="a"> 修改value为aaaaa后打印
            outPutVal(inO);
                //getAttribute: a
            //test.html:14 inO.value aaaaa
        }
    }

    //1.少量 HTML attribute 和 property 之间有着 1:1 的映射,如 id。
    //2.有些 HTML attribute 没有对应的 property,如 colspan。
    //3.有些 DOM property 没有对应的 attribute,如 textContent。
    //4.大量 HTML attribute 看起来映射到了 property…… 但却不像你想的那样!

angular中模板绑定是通过 property 和事件来工作的,而不是 attribute

特殊的attribute 绑定

[attr.aria-label]="actionName"
<td [attr.colspan]="1 + 1">
1
2
指令
属性指令
ngClass
ngStyle
ngModel
结构型指令
ngIf
ngFor
ngSwitch
ng-template *号语法
<div *ngIf="hero" class="name">{{hero.name}}</div>


<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
1
2
3
4
5
<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>
1
2
3
4
5
6
7
ng-template 会将内部包裹的元素变成注释

ng-container
ng-template 会无副作用的包裹内部元素

组件(拥有模板的指令)
ng g c components/A 创建组件
1
组件通信
1.输入属性 @Input()
//a.component.ts
@Input()
inAttr:String;

private _name:String = '';

@Input()
set inAttr2(name:String){
this._name = name;
}

get inAttr2():String{
return this._name;
}

2.输出属性 @Output()
//子组件中
@Output()
myEvent:EventEmitter<DataType> = new EventEmitter();
this.myEvent.emit(Data);

//父组件中
(myEvent)="myHandleEvent($event)"
myHandleEvent(Data:DataType){
    
}

3.中间人模式(兄弟组件通过公共的父组件传值)
4.父组件获得子组件引用 #child(只可以在组件模板中使用)

  1. @ViewChild()父组件类插入子组件 (可以在类中使用)
    被注入的计时器组件只有在 Angular 显示了父组件视图之后才能访问
    Angular 的单向数据流规则会阻止在同一个周期内更新父组件视图。应用在显示秒数之前会被迫再等一轮。
    使用 setTimeout() 来等下一轮
    @ViewChild(CountdownTimerComponent)
    private timerComponent: CountdownTimerComponent;

    ngAfterViewInit() {
    // Redefine seconds() to get from the CountdownTimerComponent.seconds ...
    // but wait a tick first to avoid one-time devMode
    // unidirectional-data-flow-violation error
    setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
    }

6.通过服务传递数据
自定义指令
ng g d myDirective/demo
1
1.属性型指令

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
selector: '[appDemo]'
})
export class DemoDirective {

constructor(private el:ElementRef) { }
// 注册事件
@HostListener('click')
show(){
console.log(this.el.nativeElement);
console.log(this.ss);
}
//指令参数,当参数名与指令名相同时,可以直接赋值给指令
@Input()
ss:String = 'aaa';
}

2.结构型指令

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

/**

  • Add the template content to the DOM unless the condition is true.
    */
    @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;
}
}
}

目录结构
依赖注入
angular实现控制反转的手段就是依赖注入
依赖注入的好处:依赖注入会让你用一种松耦合的方式去写代码,易于调试
注入器:
//只有加入@injectable()才能注入其他
construct(private productService:ProductService){...};
1
2
提供器 作用域与优先级
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}}]
1
2
3
4
5
@angular/router路由

<base href="/">
1
2
//app.module.ts
//导入路由核心模块
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
{path:'**',component:AComponent}
];

@NgModule({
...
imports: [RouterModule.forRoot(routes)]
...
})
export class AppModule { }

Routes路由配置介绍
path "**"表示匹配所有
redirectTo “表示要转走的路径”
pathMatch "full"表示匹配程度
component 表示要显示的组件
data 数据传递
children:[] 子路由
canActivate canActivate:[PermissionGuard]
canDeactivate canDeactivate:[FocusGuard]
outlet 辅助路由
resolve resolve:{Stock:StockResolve}
Router可调用navigate与navigateByUrl()
RouterLink
<a [routerLink]="['/path']">routelink</a>
<a [routerLink]="['./path']">routelink</a>
<a [routerLink]="['{outlets:{aux:'aaa'}}']">routelink</a> 辅助路由
http://localhost:4200/a(aux:aaa)
1
2
3
4
路由数据传递:
//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

ActivatedRoute 常用:this.routeInfo见上面
守卫路由
1.canActivate
export class PermissionGuard implements CanActivate{
canActivate(){
let hasPemission:boolean = Math.random() < 0.5;
return hasPemission;
}
}
1
2
3
4
5
6
2.canDeactivate
export class FocusGuard implements CanDeactivate<CComponent>{
canDeactivate(component:CComponent){
if(component.isFoucs){
return true;
}else {
return confirm('不关注一下嘛?');
}
}
}

9
3.resolve 读取数据前
@Injectable()
export class StockResolve implements Resolve<Stock>{
constructor(
private route:Router
){}
resolve(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
return new Stock(1,'name');
}
}

响应式编程:
import {Observable} from "rxjs";
Observable.from([1,2,3,4])
.filter(e => e%2 == 0)
.map(e => e*e)
.subscribe(
e => console.log(e),
err => console.error(err),
() => console.log("结束啦")
)
//4,16,结束啦

10
生命周期钩子
初始化阶段
//1.constructor
//2.ngOnChanges父组件初始化子组件输入属性时被调用 (不可变对象的改变)
ngOnChanges(changes:SimpleChanges):void{

}
//3.ngOnInit
//4.ngDoCheck 一定要判断一下你想要的变化发生时
//5.ngAfterContentInit
//6.ngAfterContentChecked
//7.ngAfterViewInit
//8.ngAfterViewChecked
1

11
变化阶段
//1.ngOnChanges
//2.ngDoCheck
//3.ngAfterContentChecked
//4.ngAfterViewChecked
1
2
组件销毁阶段
//1.ngOnDestroy
// 在路由变更时改变
1
2
ngAfterViewInit,ngAfterViewChecked
//1.子组件组装好父组件才会组装
//2.组件是在试图组装完毕调用
//3.再此方法中不可以更改视图数据

//s.component.ts
greeting(name:string){
...
}
//f.component.html
<app-child #child1></app-child>
<app-child #child2></app-child>
//f.component.ts
@viewChild("child1")
child1:sCompenent;

this.child1.greeting(...);

ngAfterContentInit,ngAfterContentChecked
投影
1.子组件
<div>
<ng-content></ng-content>
</div>
2.父组件
<SComponent>
.......
</SComponent>

表单
// 在imports中:
// ReactiveFormsModule响应式表单
// FormsModule模板式表单
1
2
3
模板式表单
// 在angular中会自动加上ngForm来处理表单,如果不用angular来处理则加上ngNoForm
//在表单中加上#myForm="ngForm",则可以在页面使用{{myForm.value | json}}去检测表单中有ngModule的value 对象名为name值
//(ngSubmit)="..."

NgForm => FormGroup
ngModel=>
ngModelGroup
<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}}


second值是:{{second.value}}
</div>

模板式表单校验
指令:
// ng g directive f/s
@Directive({
providers:[{provide:NG_VALIDATORS,useValue:mobileValidator,multi:true}]
})
1
2
3
4
响应式表单
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')
]);

FormControl
FormGroup
FormArray
<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:['']
})
});

angular表单 校验器
//自定义校验器
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}) //一次校验多个字段

22
显示错误信息
<div [hidden]="!formModel.hasError('required','nickname')"></div>
1
异步校验
状态字段:
————————————————
版权声明:本文为CSDN博主「fullSE」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_31631167/article/details/78319788

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容

  • 一.课程简介 (注意:这里的AngularJS指的是2.0以下的版本) AngularJS的优点: 模板功能强大丰...
    壹点微尘阅读 920评论 0 0
  • AngularJS是什么?AngularJs(后面就简称ng了)是一个用于设计动态web应用的结构框架。首先,它是...
    200813阅读 1,607评论 0 3
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,214评论 0 6
  • core package 概要:Core是所有其他包的基础包.它提供了大部分功能包括metadata,templa...
    LOVE小狼阅读 2,586评论 0 3
  • 终于把核心部分做的差不多了,我想想接下来大概还有哪些部分要做。 添加测试数据、商城前台的十多张页面、前后端动态交互...
    _走向孤独_阅读 154评论 0 1