Angular学习随笔

news/2023/12/1 7:52:59

最近在看angular4,随手记的一些angular的随笔。

新上手或者准备学angular的可以用作参考,第一次写博客,笔记不算完整,若老司机发现有不足指出请指出。

技术交流群:513590751

Angular程序架构

组件

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

指令 详细指令速查

允许向html添加自定义行为 

模块

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

服务

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

组件

在组件上声明模版变量


#varName

组件元数据装饰器


用来元数据附加到typescript的类上面 从而让angular把这个类识别为组件

## selecter:css的选择器,标志可以根据该选择器作为html标签

## templateUrl:指定了html文件作为组件的模版

## styleUrls:指定了组件模版中的样式

控制器


控制器是指被@component()装饰的类

包含与模版相关的所有的属性与方法

与页面相关的大部分逻辑都是编写在控制器里面

模块

@NgModule装饰器


用@NgModule装饰器生成一个模块

## 用declarations声明了模块中有什么东西(只能声明组件、指令和管道)

## 用imports声明了模块依赖的其他模块

## 用providers声明模块中提供什么服务(此处只能声明服务)

## 用bootstrap声明了模块的主组件

## 在模块中声明服务,在所有组件中都可以使用,在组件中声明服务,只能在组件中使用(每个想要被注入的服务都需要在服务提供其中声明)

新建一个Angualr项目

用angular-cli创建一个angular项目


创建:ng new my-app

启动:ng serve [--open]

    --open:在浏览器打开
    
    --routing:生成一个带route的项目
    
生成组件:ng g component [componentName]
生成服务:ng g service [serviceName]
生成管道:ng g pipe [pipeName]
生成指令:ng g directive [directiveName]
    

Angular router

名称简介
Routes路由配置,保存着哪个URL对应展示哪个组件,以及在哪个RouterOutlet中展示组件
Routerlet在HTML中标记路由内容呈现位置的占位符指令
Router负责在运行时执行路由的对象,可以通过调用其navigate()和navigateByUrl()方法来导航到一个指定的路由
RouterLink在HTML中声明路由导航用的指令
ActivatedRoute当前激活的路由对象,保存着当前路由的信息,如路由地址,路由参数等

路由配置


path:路由URL

component:路由对应的组件

    {path:"**",component:Page404Component}   //404页面,放到所有路由的最后

children:[{path:"aaa",component:AaaComponent}]子路由

redirectTo:重定向的URL

pathMatch:指定匹配方式,匹配path中的 '',(full完全匹配,prefix匹配前缀)

loadChildren:延迟加载

canActivate:[class]    //此处调用的类需要在providers里面声明,该类实现了CanActivate类 implements CanActivate

canDeactivate:[class]  //此处调用的类需要在providers里面声明,该类实现了CanDeactivate类 implements CanDeactivate<component>

resolve:{param1:value1,params2:value2}    //此处调用的类需要在providers里面声明,该类实现了Resolve类 implements Resolve<component>

路由时传递参数


传参:

    方式1:/product?id=1&name=2
    
    方式2:{path:/product/:id}  =>  /product/1
    
    方式3:{path:/product,component:ProductComponent,data:[{flag:true}]}

取值:ActivatedRoute.queryParams[id]    //适用于方式1

      ActivatedRoute.params[id]    //适用于方式2
    
      ActivatedRoute.data[0][flag]  //适用于方式3
      

参数快照

export class ProductComponent implements OnInit {
    
    private name;

    private id;

    constructor(private activatedRoute: ActivatedRoute) {
    }

    ngOnInit() {
        // 订阅方式 如果会有组件调用本身的情况就使用订阅方式
        this.activatedRoute.params.subscribe((params: Params ) => this.id = params["id"] );
        // 快照方式
        this.name = this.activatedRoute.snapshot.queryParams["name"];
        this.id = this.activatedRoute.snapshot.params["id"];
    }
    
}

辅助路由

<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>

{path:"xxx",component:XxxComponent,outlet:"aux"}
{path:"yyy",component:YyyComponent,outlet:"aux"}

<a [routerLink]="[{outlets:{aux:null}}]">xxx</a>
<a [routerLink]="[{outlets:{primary:'home',aux:'yyy'}}]">yyy</a>

primary:控制主路由

路由守卫


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

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

Resolve:在路由激活之前获取路由数据。

依赖注入


在providers中注册接口

在需要引用的类的构造方法的参数中注入

constructor(private params1:Params){}

当使用同一个接口不同的实现类时,在providers中声明providers: [{
    provide: Params,
    useClass: AnotherParams
}]

使用工厂类确定使用哪个类时,在providers中声明providers:[{
    provide: Params,
    useFactory: () => { 
        let depClass = new DepClass(); // 此处工厂方法和DepClass类耦合
        let isLogin = Math.random() > 0.5; // 可能还依赖一个外部的变量来判断需要创建哪个类
        //在这里返回要使用的类型 注意:工厂方法只会在创建第一个需要注入的对象的时候被调用一次 
    }
},DepClass]

// 为工厂方法解耦合
使用deps属性来声明工厂方法依赖的类和变量的provide属性,在providers中声明providers:[{
    provide: Params, 
    useFactory: (depClass:DepClass,isLogin) => { 
        //在这里返回要使用的类型 
    },
    deps: [DepClass,"IS_LOGIN_ENV"]
},DepClass,{
    provide:"IS_LOGIN_ENV",
    useValue:false
}]
useValue的值可以是基本类型,也可以是对象类型
angular会吧工厂方法依赖的DepClass类注入到工厂方法

数据绑定

使用插值表达式


<h1>{{productTitle}}</h1>

使用方括号将html标签的一个属性绑定到一个表达式上


<img [src]="imgUrl" />
<img src="{{imgUrl}}" />

使用小括号将组件控制器的一个方法绑定为模版上一个事件的处理器 $event(浏览器事件对象)指向触发事件的dom元素


<button (click)="clickEvent($event)">绑定事件</button>
dom属性

事件中使用 event.target.value 获取的值是html元素的dom属性(dom属性的值是会发生变化的)
html属性

使用 event.target.getAttribute("value") 获取的值是html元素的初始值(html属性是不会发生变化的)

<div class="aaa bbb" [class]="ccc">这种方式会替换原class属性的值</div>
<div class="aaa bbb" [class.ccc]="true">这种方式不会替换原class属性的值</div>
<div [ngClass]="{aaa:isTrue,bbb:isShow}">这种方式可以控制多个属性的显示</div>

双向数据绑定


<div [(ngModel)]="name">双向数据绑定</div>

管道


{{name | filter}}
eg:{{birthday | data}}// 将生日转化成日期格式
eg:{{birthday | data:'yyyy-MM-dd HH:mm:ss'}}// 将生日转化成指定日期格式

自定义管道


在项目中生成一个管道,然后在管道类的transform方法中对值进行操作。
    export class PipeName implements PipeTransform {
        transform(value: any, arg: any): any {
            // value 是要在管道做处理的值
            // arg 是管道后面跟着的参数
        }
    }

响应式编程


1、在项目模块中引入ReactiveFormsModule模块

2、在组件中声明FormControl类型的字段
    eg:formControlName

3、在页面中控件上声明[formControl]="formControlName"

4、在组件中订阅formControlName的valueChanges事件
    eg:this.formControlName.valueChanges.subscribe(value => this.keyword = value);
    

组件间通讯

组件的输入输出属性

输入属性

在需要注入的属性上用@Input注解
在父组件中用[propName]="value"来赋值
输出属性

在子组件属性上用@Output解属性类型为EventEmitter<DataType>类型
@Output()
prop:EventEmitter<DataType> = new EventEmitter();
用 prop.emit(dataTypeObj)

在父组件中声明dataTypeObj:DataType = DataType();//用来存放子组件Output出来的属性

在父组件引用子组件的标签上用事件订阅来订阅自组建发射的事件
用<child-comp (prop)="propHandler($event);"></child-comp>
// 监控的事件名 prop 和@Output中的参数一致,不传参时默认和属性名一致

在父组件中声明
propHandler(event:DataType){
    // 把子组件Output出来的属性赋值到父组件的属性上
    this.dataTypeObj = event;
}

使用中间人模式传递数据


两个子组件,通过@Output数据到父组件和@Input从父组件接收数据来实现组件间通讯,父组件为中间人

组件生命周期以及angular的变化发现机制

组件钩子:

想要使用这些钩子,需要先实现对应的接口

被调用一次的钩子
    
    constructor(组件构造方法,调用该方法时,组件的输入属性没有值)
    
    ngOnInit(初始化组件或指令,调用该方法时,OnChanges方法已被调用,组件的输入属性有值)
    
    ngAfterContentInit(和angular的内容投影相关的)
    
    ngAfterViewInit(和angular的视图初始化和检查相关的,在此方法不可修改组件的属性)
    
    ngOnDestroy(组件销毁,在路由到其他组件时当前组件被销毁)
    
被调用多次的钩子
    
    ngOnChanges(父组件初始化或修改子组件的输入属性的值的时候被调用,如果一个方法没有输入属性,则该方法不会被调用)
    
    ngDoCheck(用来检测,在每个angular的变更检测周期调用)
    
    ngAfterContentChecked(和angular的内容投影相关的)
    
    ngAfterViewChecked(和angular的视图初始化和检查相关的,在此方法不可修改组件的属性)

调用顺序:
    
    constructor、ngOnChanges、ngOnInit、ngDoCheck、ngAfterContentInit、ngAfterContentChecked、ngAfterViewInit、ngAfterViewChecked、ngAfterContentChecked、ngAfterViewChecked
父组件调用子组件的方法

#在父组件的模块中调用子组件的方法

1、在子组件上声明模版变量 #childName
2、在父组件中声明一个类型为 ChildeComponent 的变量 child
3、用 @ViewChild("childName") 注解声明的变量 child
4、在代码块中用 this.child.methodName(args) 来调用子组件的方法

#在父组件的模版中调用子组件的方法

1、在子组件上声明模版变量 #childName
2、在父组件的模版中绑定事件 (click)="childName.methodName('args')"

父组件内容投影到子组件中


#父组件
<div>
    <child-comp>
        <div class="header">这是头部</div>
        <div class="footer">这是底部</div>
    </child-comp>
</div>

#子组件
<div>
    <ng-content select=".header"></ng-content>
    <ng-content select=".footer"></ng-content>
</div>

定义单个投影点时可以不写class属性和select属性

表单处理

模版式表单


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

可用指令


NgForm

NgModel

NgModelGroup

用#myForm来声明表单的模版变量,在表单的onSubmit="onSubmit(myForm.value,myForm.valid)"来传入表单的值和表单是否通过验证

生成指令


@Directive({
    selecter: "[dirName]", // 在html上作为属性使用
    providers: [{provide: NG_VALIDATORS, useValue: mobileValidator, multi: true}] // mobileValidator是已经声明的验证器
})

响应式表单


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

可用对象


FormControl

userinfo: FormControl = new FormControl("aaa");

FormGroup

FormGroup是多个FormControl的集合

FormArray

使用


方式一、
formModel: FormGroup = new FormGroup({
    username: new FormControl("初始值"),
    password: new FormControl(),
    email: new FormArray([
        "a",
        "b"
    ])
});

方式二、
constructor(fb: FormBuilder){
    this.formModel = fb.group({
        username: ["初始值", Validators.required], // 第二个参数是校验器,可以传一个数组,第三个参数是异步校验器
        password: [""],
        email: fb.array([
            "a",
            "b"
        ])
    });
}

<!-- 使用 novalidator 阻止浏览器默认的表单验证如:(required) -->
<form [formGroup]="formModel" novalidator>
    <!-- required 验证表单是否为空 -->
    <input type="text" ngModel required formControlName="username"/>
    <!-- 第一个参数是校验器返回的错误对象的key,第二个参数是校验的字段 -->
    <div [hidden]="formModel.hasError('required','username')">用户名不能为空</div>
    <input type="text" formControlName="password"/>
    <div *ngFor="let e of email;let i = index;" formArrayName="email">
        <input type="text" [formControlName]="i"/>
    </div>
</form>

表单验证

校验器


funcName(control: AbstractControl) {[key: string]: any} {
    return null;
}

eg:

mobileValidator(control: FormControl) any {
    let valid = true;
    return valid ? null : {mobile : true};
}

constructor(fb: FormBuilder){
    this.formModel = fb.group({
        mobile: ["", this.mobileValidator]
    });
}

onSubmit() {
    let isValid:boolean = this.formModel.get("username").valid;  // 获取字段是否通过验证
    let error:any = this.formModel.get("username").errors;  //获取字段未通过验证的错误信息
    this.formModel.valid; // 用来判断表单是否合法
}

异步校验器


异步校验器作为字段构造的第三个参数传入
funcName(control: AbstractControl) {[key: string]: any} {
    // 返回的对象用Observable.of方法包裹,delay延迟5s
    return Observable.of({}).delay(5000);
}

eg:

mobileAnsycValidator(control: FormControl) any {
    let valid = true;
    return Observable.of(valid ? null : {mobile : true}).delay(5000);
}

constructor(fb: FormBuilder){
    this.formModel = fb.group({
        mobile: ["", this.mobileValidator, this.mobileAnsycValidator]
    });
}

与服务器通讯

引入Http模块:


    1、import Http from "@angular/http";
    
    2、在cunstructor方法中注入:cunstructor(http: Http)
    
    3、使用this.http.get("url",data)获取数据,并且用.map(res => res.json())把获取到的数据转换成json格式
    
    4、用Observable类型的变量接收数据
    
    5、订阅Observable类型的变量,并且用obs.subscribe(data => this.product = data)来赋值给变量
    
proxy.conf.json配置
    // 意指当前请求是以/api开头时,把请求转发到http://loacalhost:8000
    {
        "/api": {
            "target": "http://loacalhost:8000"
        }
    }
    // 在package.json中配置
    ng serve 命令添加参数 --proxy-config proxy.conf.json
    

使用websocket协议与后台通信

service


import {Injectable} from '@angular/core';
import {Observable} from "rxjs/Observable";

@Injectable()
export class WebSocketService {

    ws: WebSocket;

    constructor() {
    }
    
    // 根据传入的url创建一个websocket协议
    createObservableScoket(url: string): Observable<any> {
        // 创建websocket服务
        this.ws = new WebSocket(url);
        return new Observable(observer => {
            // 返回成功时执行的方法
            this.ws.onmessage = event => observer.next(event.data);
            // 返回错误时执行的方法
            this.ws.onerror = event => observer.error(event);
            // 关闭websocket流时执行的方法
            this.ws.onclose = event => observer.complete();
        });
    }

    sendMessage(msg: string) {
        this.ws.send(msg);
    }
}

component


export class SearchComponent implements OnInit {

    constructor(private wsService: WebSocketService) {
    }

    ngOnInit() {
        // 订阅websocket返回的值
        this.wsService.createObservableScoket("ws://localhost:8085").subscribe(
            data => console.log(data),
            error => console.log(error),
            () => console.log("webSocket已结束!")
        );
    }

}

http://www.niftyadmin.cn/n/1938674.html

相关文章

团队贡献分分配

团队贡献分分配 相比较更倾向于第二种分配方式 组长是该项任务的负责人&#xff0c;不论该项任务完成的好坏&#xff0c;组长都应该为其负责&#xff0c;所以组长的分数等于该小组交付物的评分。 而小组成员的初始分数应均与组长相同&#xff0c;组长根据其组员的表现对其进行加…

CGAN

生成网络的输入是一个带标签的随机数&#xff0c;具体操作方式是生成一个N维的正态分布随机数&#xff0c;再利用Embedding层将正整数&#xff08;索引值&#xff09;转换为N维的稠密向量&#xff0c;并将这个稠密向量与N维的正态分布随机数相乘。 num_classes10 latent_dim10…

iterator_category

/* * 迭代器类型 * 1. input ierator * 2. write iterator * 3. forward iterator 在迭代器所形成的区间上进行读写操作 * 4. bidirectional iterator 可双向移动 * 5. random access iterator */// 在执行时期决定使用哪一个版本会影响程序效率&#xff0c;最好在编译期选择正…

基于NDK编译Android平台的FFmpeg动态库

需求 FFmpeg在Linux平台&#xff08;如Ubuntu&#xff09;上的支持已经比较完善了&#xff0c;如前述文章介绍 http://blog.csdn.net/ericbar/article/details/73702061&#xff0c;我们很容易就可以基于FFmpegSDL实现一个播放器&#xff0c;比如FFmpeg自带的ffplay程序&#…

资源监控

后台开一个2G的文件cat 1.log[rootlocalhost ~]# mpstat 3 100>1.logLinux 2.6.13 (localhost.localdomain) 2005年12月15日 13时48分25秒 CPU %user %nice %system %iowait %irq %soft %idle intr/s13时48分28秒 all 96.00 0.00 4.00 0.00 0.00 0.00 0.00 401.6713时48分31…

MYSQL 升序排序但值为0的排最后

如一张表的数据如下&#xff1a; 需要根据gz列的值进行升序排序&#xff0c;但值为0的排在最后面&#xff0c;即最终结果如下图&#xff1a; 具体 实现方法如下&#xff1a; 1.Order BY表达式 SELECT nian ,gz from Tbl ORDER BY gz!0 desc,gz 2.算术法 SELECT nian ,gz,1/gz a…

sql injection笔记(一)

1、无过滤后台代码&#xff1a; $sql"SELECT * FROM user WHERE username "; $sql.$_GET["name"].""; $result mysql_query($sql); 正常提交参数nameroot 闭合单引号。改变sql查询语句&#xff0c;测试是否存在注入漏洞&#xff0c;and ‘1’‘…

rapidjson 的封装学习

#pragma once #include "Util.h" #include "rapidjson/writer.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/document.h" NAMESPACEBEGIN(DEF) //参考 https ://github.com/qicosmos/SmartDB1.03/blob/master/JsonCp…

JavaScript splice() 、slice() 方法

定义和用法 splice() 方法向/从数组中添加/删除项目&#xff0c;然后返回被删除的项目。 slice() 方法可从已有的数组中返回选定的元素。 注释&#xff1a;该方法会改变原始数组。 语法 arrayObject.splice(index,howmany,item1,.....,itemX) 参数描述index必需。整数&#xff…

Docker容器技术-优化Docker镜像

一、优化Docker镜像 1.降低部署时间 一个大的Docker应用是如何影响在新Docker宿主机上的部署时间。 &#xff08;1&#xff09;编写Dockerfile创建一个大Docker镜像 [rootbogon ~]# cat Dockerfile FROM debian:jessieRUN dd if/dev/urandom of/largefile bs1024 count524288&…

怎么理解反向代理 reverse proxy

反向代理( reverse proxy ) 理解反向代理前先得说说什么是代理&#xff0c;比如我们想FQ去使用国外的某些网站&#xff0c;比如想使用 google 提供搜索&#xff0c;那么我们就得需要一个代理。 我们在客户端这边配置一下代理服务器&#xff0c;然后当我们访问 google 服务的时候…

MEAN框架介绍

近期在Angular社区的原型开发人员间。一种全Javascript的开发架构MEAN正突然流行起来。其首字母分别代表的是&#xff1a;(M)ongoDB——NoSQL的文档数据库&#xff0c;使用JSON风格来存储数据&#xff0c;甚至也是使用JS来进行sql查询&#xff1b;(E)xpress——基于Node的Web开…

MTCNN网络

转载&#xff1a;人脸检测与对齐之MTCNN网络

人脸表情识别

--------------------------训练模型-------------------------------------------- from keras.models import Sequential from keras.layers import Conv2D, MaxPool2D, Activation, Dropout, Flatten, Dense from keras.optimizers import Adam from keras.preprocessing.i…

薛XX后代的IQ CSU1597【循环节】或【快速幂】

薛先生想改变后代的IQ&#xff0c;为此他发明了一种药&#xff0c;这种药有三种属性&#xff1a;A, B,P。他父亲的智商为X&#xff0c;薛先生的智商为Y&#xff0c;用了这种药之后&#xff0c;薛先生的孩子的智商就可以变为(AXBY) mod P。后代的智商以此类推。 现在给定X和Y&am…

在ubuntu16.04下测试ffplay程序

下载FFmpeg及SDL源码 离上次博文发布已经有一段时间了&#xff0c;这次我们来测试一下强大的FFmpeg播放器程序ffplay&#xff0c;它是FFmpeg原生附带的。 本文编写时&#xff0c;FFmpeg的最新版本是3.4.2&#xff0c;从官网ffmpeg.org上下载ffmpeg-3.4.2.tar.xz源码&#xff…
最新文章