1. 新建组件 ng n c hello
2. 插值语法 {{ content }}
3. 属性绑定用 []
<p-dataTable [value]="listdata" selectionMode="multiple"></p>
或者
<p-dataTable [value]="listdata" [selectionMode]="'multiple'"></p>
<div [class]="'box'"></div>  // 必须是字符串    [class]="box"这样写box是变量
<h3 [class.xxy-table]="true"></h3>       //
<h3 [class]="{'xxyTable': true}"></h3>   //对象条件渲染
ngClass 是指令 和直接写class一样 
<h3 [ngClass]="{'active': isActive}"></h3>    
<h3 [class]="['xxyTable', 'xxyBox']"></h3>   //数组渲染
<p [style]="{ width: '170px', height: '30px' }"></p>  //样式绑定
ngStyle
4. 条件判断 ngIf
<p *ngIf="isShow"></p>
<ng-container *ngIf="isShow; else Show">
	<p></p>
</ng-container>
<ng-template #Show>
  <p></p>
</ng-template>
5. 循环语句
let elementDatas: string[] = ['小明', ‘小红]
<div *ngFor="let data of elementDatas let i = index">
{{i}}                                                      //下标
{{data}}                                                   // 值   
</div>
6. 事件绑定
<button (click)="handleClick()"></button>
7. ViewChild 绑定获取dom元素 (类似vue2中的ref)

通过 ViewChild 装饰器 获取 dom

import { ViewChild } from "@angular/core";

<div #text1></div>

@ViewChild("text1") text1: ElementRef;

this.text1.nativeElement
8 表单的双向数据绑定 (和vue的v-model类似)

首先全局引入app.module.js

import {FormsModule} from "@angular/forms";
imports: [ FormsModule ]

使用

<input maxlength="20" placeholder="名称" [(ngModel)]="prodectName"

export class ShopchecklistComponent implements OnInit {
  prodectName: string = ''
}
9.动态表单 (和第8点类似都是实现表单绑定)

首先全局引入app.module.js

import {ReactivFormsModule} from "@angular/forms";
imports: [ ReactivFormsModule ]

使用,要注册一个表单控件,就要导入 Formcontrol 类并创建一个 Formcontrol 的新实例,将其保存为类的属性。

<input type='text' [formControl]="productName" />
 使用必须 .value
<p>{{productName.value}}</p>

import { FormControl } from '@angular/forms'

export class ShopchecklistComponent implements OnInit {
  productName: FormControl = new FormControl('')
  
  //修改值
  updateName(val:string) {
    this.productName.setValue(val)
	}
}

10. 动态表单组(引入第9步的ReactivFormsModule)

使用 FormsGroup创建

<form [formGroup]="personMes" (submit)="OnSubmit()">
  <input type="text" formControlName="name"><br>
  <input type="text" formControlName="address"><br>
  <button>提交</button>
</form>

import { FormControl, FormGroup } from '@angular/forms';

export class ReativeFormsComponent implements OnInit {
  personMes: FormGroup = new FormGroup({
    name: new FormControl(),
    address: new FormControl()
  })

  OnSubmit(){
    console.log(this.personMes.value)
  }
}

11. 基础表单验证

(不常用)表单项使用required启用验证,#自定义名字="ngModel",模版引用变量

<form>
  账号:<input type="text" required #nameInp="ngModel" [(ngModel)]="fromData.name">
    <p>验证信息{{nameInp.valid}}</p>    //返回布尔值
  密码:<input type="text" required #passInp="ngModel" [(ngModel)]="fromData.password">
    <p>验证信息{{passInp.valid}}</p>    //返回布尔值
  <button (click)="OnSubmit(nameInp)">提交</button>
</form>

export class ReativeFormsComponent implements OnInit {
  fromData={
    name: '',
    password: ''
  })

  OnSubmit(val){
    console.log(val)
  }
}
状态 为true时的类 为false时的类
控件已经被访问过 Ng-touched Ng-untouched
控件值已经变化 Ng-dirty Ng-pristine
控件值是有效的 Ng-valid Ng-invalid
12. 自定义表单验证

引入 FormGroup, FormBuilder, Validators

<form [formGroup]="valiDataForm">
  <input type="text" formControlName="userName"><br>
    <p *ngIf="valiDataForm.get('userName')?.errors?.required">请输入6-18位名称</p>
		<p *ngIf="valiDataForm.get('userName')?.errors?.minlength">长度在6-18位</p>
  <input type="text" formControlName="password"><br>
  <input type="text" formControlName="phone"><br>
  <button  (click)="OnSubmit()">提交</button>
</form>



import { FormControl, FormGroup, FormBuilder, Validators } from '@angular/forms';

constructor(private fb: FormBuilder) {}   //注入方法

valiDataForm: FormGroup = this.fb.group({      //通过FormBuilder生成控件组
	userName: ['', [Validators.required, Validators.maxLength(18), Validators.minLength(6)]],
	password: ['', [this.passwordVal]],
	phone: ['', [Validators.required, this.phoneVal]],
})
//自定义校验方法
passwordVal() {}
//自定义校验方法
phoneVal(phone: FormControl):object {
  const value = phone.value || ''
  if(!value) return { desc: '请输入手机号'}
  const valid = /[0-9]{11}/.test(value)
	return valid ? {} : {desc: '请输入正确的手机号'}
}


//提交时获取
OnSubmit() {
  console.log(this.valiDataForm.get('userName'))  //获取校验信息
}
13. 管道 (类似vue里的过滤器)

管道的作用就是传输,不同的管道具有不同的作用。

angular中自带的pipe函数

{{DateTime | date: 'yyyy-MM-dd HH:mm:ss'}}

export class EditTheDeclarationComponent implements OnInit {
    DateTime: Date = new Date() //获取本地当前时间
 }

常用的内置管道

管道 类型 功能
DatePipe 纯管道 日期格式化
JsonPipe 非纯管道 使用JSON.stringify()将对象转成json字符串
UpperCasePipe 纯管道 将文本中的字母全部转在大写
LowerCasePipe 纯管道 将文本中的字母全部转成小写
TitleCasePipe 将文本转换成标题格式
DecimalPipe 纯管道 数值格式化
CurrencyPipe 纯管道 货币格式化
PercentPipe 纯管道 百分比格式化
SlicePipe 非纯管道 数组或字符串取切割
I18nPluralPipe 根据expression的值匹配mapping中的值,并将匹配之后的值展示出来
I18nSelectPipe 根据expression匹配mapping中的值,并且返回|匹配之后的值
14. 生命周期
钩子函数 用途 触发时机
ngOnChanges() Angular 设置或重新设置数据绑定的输入属性时响应。该方法接受当前和上一属性值的SimpleChanges 对象注意,这发生的非常频繁,所以你在这里执行的任何操作都会显著影响性能。 在 ngOnInit()之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。注意,如果你的组件没有输入,或者你使用它时没有提供任何输入,那么框架就不会调用ngOnChanges()。
ngOnInit() 在Angular 第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。 在第一轮 ngOnChanges() 完成之后调用,只调用一次。
ngDoCheck() 检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应。 紧跟在每次执行变更检测时的 ngOnChanges ()和 首次执行变更检测时的 ngOnInit()后调用。
ngAfterContentInit() 当 Angular 把外部内容投影进组件视图或指令所在的视图之后调用。 第一次 ngDocheck() 之后调用,只调用一次。
ngAfterContentChecked() 每当 Angular 检查完被投影到组件或指令中的内容之后调用 ngAfterContentInit 和每次 ngDoCheck()之后调用
ngAfterViewInit() 当 Angular 初始化完组件视图及其子视图或包含该指令的视图之后调用 第一次 ngAfterContentChecked) 之后调用,只调用一次
ngAfterViewChecked() 每当 Angular 做完组件视图和子视图或包含该指令的视图的变更检测之后调用。 ngAfterViewInit() 和每次ngAfterContentChecked()之后调用。
ngOnDestroy() 每当 Angular 每次销毁指令/组件之前调用并清扫。在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏 在 Angular 销毁指令或组件之前立即调用。
15. 组件交互(类似vue3.0 setup语法糖写法)

https://blog.csdn.net/qq_37516758/article/details/129136190

  • 父组件给子组件传值
父组件
1. 定义数据
export class ShopchecklistComponent implements OnInit {
	messageTitle: string = '某某页面头'
}
2.父组件在调用子组件的时候传值
<app-title [messageTitle]="messageTitle"></app-title>

子组件 app-title
1.需要引入Input
import { Input } from '@angular/core';
2.接收值
export class TitleComponent {
  @Input() messageTitle: string; 
}
3.使用
<p>{{messageTitle}}</p>
  • 子组件给父组件传值
子组件 app-child
1.引入Output 和  EventEmitter
import { Output,EventEmitter } from '@angular/core';
2.定义方法 handleChange
@Output handleChange = new EventEmitter();
3.执行方法并传递数据
send() {
  this.handleChange.emit("给父组件传递的数据")
}

父组件
1.执行子组件emit出来的事件名字然后自定义事件
<app-child #child  (handleChange)="handleChange($event)"></app-child>
handleChange(e: string) {
  console.log(e, '获取子组件的值')
}
  • 父组件获取子组件的数据(ViewChild)
父组件
<app-child #handleChild></app-child>

import { ViewChild } from "@angular/core";

@ViewChild("handleChild") handleChild : any;

假设有一个子组件方法为run()或者子组件数据为name
this.handleChild.run();
this.handleChild.name;
16. angular中服务与注入

https://blog.csdn.net/weixin_43536485/article/details/109466208

服务的作用:抽离js,例如封装http请求

  • 输入以下命令创建服务,自动在service中创建2个文件hero.service.spec.tshero.service.ts
ng g service service/hero
  • hero.service.ts 中引入@Injectable装饰器
import { Injectable } from '@angular/core';

//@injectable的意思是声明该服务类可被注入到其他的service、component或者其他实例中去
@Injectable({
  providedIn: 'root'		//providedIn 声明服务提供给哪个模块使用,
  							//root 实际上是 AppModule 的别名,因此不需要额外导入 AppModule。
})
export class HeroService {
  constructor() {}
  get(){
    return '这是服务里的数据'
  }
}

  • 在app.module.ts文件中声明服务

先import导入服务,再往providers数组中添加服务名

import {HeroService} from './service/hero.service';	
//NgModule 最根本的意义是帮助开发者组织业务代码 
//开发者可以利用 NgModule 把关系比较紧密的组件组织到一起
//来定义本模块的元数据
@NgModule({
  //用来放组件、指令、管道的声明
  declarations: [],
  //用来导入项目中需要的模块
  imports: [],
  //需要使用的 Service 都放在这里。
  providers: [
    HeroService
  ],
})

  • 注入组件中,在组件中使用
import { HeroService } from '../../service/hero.service'	//导入服务文件
//这其实需要当做一个整体来看,上面一段被称作装饰器,用于装饰AppComponent这个class:

export class HomeComponent implements OnInit {
  //也可以使用下面定义属性的来使用服务(不提倡)
  //public heroService:HeroService = new HeroService();
  constructor(public heroService:HeroService) { 	//把服务当作参数注入到构造函数中去
    console.log(heroService.get());				//使用服务方法 因为在构造函数里,可以不用加this		
  }
  getChild(){
    console.log(this.heroService.get());		//使用服务里的方法
  }
}

17. 路由

路由: https://blog.csdn.net/lwf3115841/article/details/128275051

嵌套(父子)路由: https://blog.csdn.net/I_r_o_n_M_a_n/article/details/115718843

路由query参数(编程式):https://www.cnblogs.com/leileilei/p/9697898.html