angular4学习笔记(基础篇)

第二章学习笔记

Angular程序架构

组件:是Angular应用的基本构建块,你可以把一个组件理解为一段带有业务逻辑和数据的html

模块:模块用来将应用中不同的部分组织成一个Angular框架可以理解的单元

服务:用来封装可重用的业务逻辑

指令:允许你向html元素添加自定义行为

环境搭建

这里写图片描述

第三章 使用Angular Route路由

路由基础

这里写图片描述

路由传参

1.在查询参数中传递数据

/product?id=1&name=2  =>  ActivatedRoute.queryParams[id]
[routerLink]="['/product']" [queryParams]="{id:1}"
this.routeInfo.snapshot.queryParams['id']

2.在路由的路径中传递数据

{path:/product/:id}  =>  /product/1  =>  ActivatedRoute.params[id]
[routerLink]="['/product',1]" 
this.routeInfo.snapshot.params['id']

3.在路由配置中传递数据

{path:/product,component:ProductComponent,data:[{isProd:true}]} => ActivatedRoute.data[0][isProd]

参数快照和参数订阅(subscribe)

this.routeInfo.snapshot.params['id'] //参数快照
this.routeInfo.params.subscribe((params:Params)=>{this.id=params['id']}) //参数订阅,解决相同页面改变参数的问题

路由重定向:在用户访问一个特定的地址时,将其重定向到另一个指定的地址

www.aaa.com => www.aaa.com/products

 { path: '', redirectTo: '/home', pathMatch: 'full' } /是重定向到根路由,不加是在子路由中找

子路由

 { path: '', redirectTo: 'home', pathMatch: 'full' },
  {
    path: '', component: MessageHomeComponent,
    children: [
      { path: 'home', component: MessageCenterComponent },
      { path: 'resource', component: ExternalResourceComponent },
    ]
  }

[routerLink]="['./home]"    ./表示当前路由的子路由,/表示是从根路由开始

辅助路由

<router-outlet></router-outlet> //主插座  独立变化
<router-outlet name="aux"></router-outlet>//辅助插座
{path:'xxx',component:XxxComponent,outlet:'aux'}
{path:'yyy',component:YyyComponent,outlet:'aux'}

[routerLink]="[{outlets:{aux:'xxx}}]" //辅助路由与主路由无关
[routerLink]="[{outlets:{primary:'home',aux:'yyy}}]" //辅助路由跳到yyy的同时,主路由也跳到home
[routerLink]="[outlets:{aux:null}]"  //不使用辅助路由

路由守卫

CanActivate:处理导航到某路由的情况

CanDeactivate:处理路由从当前路由离开的情况

Resolve:在路由激活之前获取路由数据 (带着数据进去路由,使其进去就有数据)

第四章 依赖注入

依赖注入:Dependency Injection 简称DI 控制反转:Inversion of Control 简称IOC

**使用依赖注入的好处:**1.松耦合,可重用 2.提高可测试性

这里写图片描述

provider提供的作用域:

​ 1.声明器声明在模块中时,对模块中所有组件可见

​ 2.声明器声明在组件中时,只对声明它的组件及其子组件可见

​ 3.当模块的和组件中的provide相同时,组件中的声明器覆盖模块中的

​ 4.优先在模块中声明

服务中的@Injectable():意思是该服务可以注入其他服务

第五章 数据绑定、响应式编程和管道

数据绑定:默认单向绑定

​ 1.使用插值表达式{{}}

​ 2.使用[]绑定属性

​ 3.使用()绑定事件

DOM属性和Html属性,angular改变的是DOM属性,html属性不会发生变化
DOM属性绑定
html属性绑定
HTML属性绑定:

​ 1.基本Html属性绑定 <td [attr.colspan]="tableColspan">Something<td>

​ 2.CSS类属性绑定

<div class="aaa bbb" [class]="someExpression">something</div>    表达式的值会完全替换掉class的值
<div [class.special]="isSpecial">something</div>   根据boolean值判断是否需要special
<div [ngClass]="{aaa:isA,bbb:idB}">something</div> 

​ 3.样式绑定

<button [style.color]="isSpecial?'red':'green'">red</button>
[style.font-size.px] //带单位
[ngStyle]="{}"

双向数据绑定:[()]

内置管道

date:'yyyy-MM-dd HH:mm:ss'
number:'2.1-4'  //两位整数,小数最少1(默认为0)位最多4(默认为3)位
json  //JSON.stringify 
uppercase  //所有小写转化为大写字母
lowercase  //所有大写转化为小写
currency: 'CNY': true: '3.1-3'  //货币管道
percent  //百分数
slice:start[:end]  //截取 slice()
async  //异步流

自定义管道

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Pipe({
    name: 'textFiltering'
})
export class TextFilteringPipe implements PipeTransform {
     transform(value: any, args?: any): any {  
         //value是管道前面的值,args是管道后面的可选参数
        value = value || '暂无获取内容';
        return this.sanitizer.bypassSecurityTrustHtml(value);
    }
}
<div [innerHtml]="data?.content| textFiltering"></div> //data?.content为管道的value值
<span>发布时间:{{item?.startDate | date:'yyyy-MM-dd'}}</span> //'yyyy-MM-dd'为管道的args

第六章 组件间通信

父组件传值给子组件

父组件:

<app-index [title]="title" [run]="run"></app-index>

子组件:

import { Input } from '@angular/core';
@Input() title;
@Input() run;
//这样就可以直接使用{{title}},和this.run()在子组件使用父组件的值和方法。

子组件传值给父组件

子组件中:

import { EventEmitter, Input, Output } from '@angular/core';
@Output() selectionChange = new EventEmitter();
//事件中
 this.selectionChange.emit("我是子组件的数据");

父组件中

// selectionChange即是子组件发送的数据
<app-index (selectionChange)="getData($event)"></app-index>
// ts文件中:
getData(msg:string)
{
     console.log(msg);// 接收到的数据
}

父组件主动调用子组件

// 引用子组件
<app-index #index></app-index>
// 使用子组件中的方法
<button (click)="index.childRun()">调用index中的方法</button>

也可以在ts文件中调用:

// 引用子组件 html文件
<app-index #index></app-index>
<button (click)="parentClick(index)">调用index中的方法</button>
// ts 文件
parentClick(obj)
{
    obj.childRun();
}

ViewChild主动获取数据:

在页面中引入ViewChild

import { ViewChild } from '@angular/core';
@ViewChild("index") index;
// html中引用组件
<app-index #index></app-index>  //#index相当于是一个选择器,包含模板
<button (click)="parentClick()">调用index中的方法</button>
// ts文件中使用子组件的方法和数据
parentChild()
{
    this.index.childRun();
}

组件生命周期函数

生命周期函数

(红色的只执行一次,绿色的执行多次)

调用顺序

  1. cunstructor- 构造
  2. ngOnChanges - 当数据绑定输入属性的值发生变化时调用
  3. ngOnInit - 在第一次 ngOnChanges 后调用,只调用一次
  4. ngDoCheck - 自定义的方法,用于检测和处理值的改变,调用特别频繁
  5. ngAfterContentInit - 在组件内容初始化之后调用,它主要用于获取通过 @ContentChild 或 @ContentChildren 属性装饰器查询的内容视图元素。
  6. ngAfterContentChecked - 组件每次检查内容时调用
  7. ngAfterViewInit - 组件相应的视图初始化之后,调用它主要用于获取通过 @ViewChild 或 @ViewChildren 属性装饰器查询的视图元素。
  8. ngAfterViewChecked - 组件每次检查视图时调用
  9. ngOnDestroy - 指令销毁前调用

ngAfterViewInit和ngAfterViewChecked钩子注意:

  1. 子组件调用完毕之后,父组件才调用
  2. 不能再这两个函数中改变绑定到视图中的值,可以用
setTimeout(()=>{
    this.message="Hello"
},0)

投影

父组件中:

<app-child>
    <div class="header">header这是父组件投影到子组件中的内容</div>
    <div class="footer">footer这是父组件投影到子组件中的内容</div>
</app-child>

子组件中:

<ng-content select=".header"></ng-content> //父组件的header内容投影到这里
<ng-content select=".footer"></ng-content> //父组件的footer内容投影到这里

第七章 表单处理

模板式表单:表单的数据模型是通过组件模板中的相关指令来定义的,因为使用这种方式定义表单的数据模型时,我们会受限于HTML的语法,所以模板驱动方式只适合用于一些简单的场景。

响应式表单:使用响应式表单时,你通过编写TypeScript代码而不是Html代码来创建一个底层的数据模型,在这个模型定义好以后,你使用一些特定的指定,将模板上的Html元素与底层的数据模型连接在一起。

模板式表单需要引入FormsModule

响应式表单需要引入ReactiveFormsModule

import { FormsModule,ReactiveFormsModule } from "@angular/forms"; 

模板式表单:

<form action="/login" method="post">   //angular会默认改为ngForm,当点击登录时,不会走/login
    <div>用户名:<input type="text"/></div>
    <div>密码:<input type="password"/></div>
    <button type="submit">登录</button>
</form>
<div ngForm></div>  //效果同form
<form action="/login" method="post" ngNoForm> </form> //此刻angular不会接管该表单,会走/login

响应式表单

响应式表单指令

html:

<form [formGroup]="formModel" (submit)="onSubmit()">
    <input formControlName="username">
    <div formGroupName="dateRange">
        起始时间:<input type="date" formControlName="from">
        截止时间:<input type="date" formControlName="to">
    </div>
    <div>
        <ul formArrayName="emails">
            <li *ngFor="let e of this.formModel.get('emails').controls;let i=index;">
                <input type="text" [formControlName]="i">
            </li>
        </ul>
        <button type="button" (click)="addEmail()">增加Email</button>
    </div>
    <div>
        <button type="submit">保存</button>
    </div>
</form>

ts:

import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';
export class ReactiveFormComponent implements Oninit{
    cunstructor(
     private fb: FormBuilder,
    ){}
    formModel:FormGroup = new FormGroup({  // this.fb.group({})
        dateRange:new FormGroup({
            from:new FormControl(), //from:['初始值',检验方法,异步的校验方法]
            to:new FormControl()        }),
        emails:new FormArray([
            new FormControl("aaa@a.com"),
            new FormControl("bbb@b.com")
        ]),
        userName:new FormControl('aaa')
    })  
    addEmail(){
        let emails=this.formModel.get("emails") as FormArray;
        emails.push(new FormControl());
    }   
}

表单校验:

预定义校验器,Validators.XXX

required、minLength()、maxLength()

formModel:FormGroup=this.fb.FormGroup({
    userName:['',[Validator.required,Validators.maxLength(20)]]
})
//验证
this.formModel.get('userName').valid  //boolean
this.formModel.get('userName').errors //打印错误
*ngIf="this.formModel.hasError('required','userName')" //下载html里做提示判断
this.formModel.getError('equal','passwordsGroup')?.descxxx  //自己写的验证器里的错误提示

状态字段

touched和untouched 字段是否获取过焦点

pristine和dirty 字段的值未被改变过时,pristine为true,dirty为false

pending 当字段进行异步校验时,pending为true

针对所有的这些状态字段,Angular都会自动根据其状态为其添加一些样式,你可以通过定义这些样式,来个性化dom元素在不同状态下的外观 以下:

ng-untouched, ng-pristine, ng-invalid ng-touched, ng-dirty, ng-valid

第八章 与服务器通讯

第九章 构建和部署

构建:编译和合并(将typeScript代码编译成静态文件)

​ 执行 ng build或者npm run build 之后,在项目app文件夹下回增加一个dist文件夹

部署:与服务器整合

​ 将构建以后的dist里的所有文件复制到服务器里去,有时候会找不到路径,需要在

​ appModule.ts中

 providers: [{provide: LocationStrategy, useClass: HashLocationStrategy}]

​ 这样设置后,访问angular站点,会自动在根节点后面加一个#锚点。再次刷新便不会报404错误了。

多环境:一套代码支持多种环境

​ 在.angular-cli.json中,不同环境对应不同的环境配置

"environments": { //几个环境对象的属性保持一致
    "source":"environments/environment.ts",
    "dev": "environments/environment.ts",
    "test": "environments/environment.test.ts",
    "prod": "environments/environment.prod.ts"
}

​ 想要项目启动的环境,在package.json中:

"scripts": {
     //"start": "ng serve --proxy-config proxy.conf.json", 
    "start": "ng serve --env=prod --proxy-config proxy.conf.json", 
}

​ 想要部署中更换环境,执行ng build –env=prod或者 nom run build –env=prod

展开阅读全文

没有更多推荐了,返回首页