一、组件内部语法
1.插值语法
{{}}可以看作一小段js执行的部分
将ts声明的变量引入、字符串拼接、三元表达式、简单的数学计算
2.绑定
(1)属性绑定
<div [id]="'box'"></div>
<div [id]="box"></div>会将box看作变量,去ts中寻找变量,如果没声明就会报错
可以绑定id、class、
(2)类绑定:
<h3 [class.xx]="true">类绑定</h3>
//xx是类名,可以随意写。true可以直接写或者声明变量。
<h3[class]="'xxx yyy'">多个类名绑定</h3>
<h3[class]="{'xxx':true,'yyy':true}"//通过变量动态改变是否渲染
<h3[class]="['xxx','yyy']"></h3> //数组渲染
(3)样式绑定
<h3 [style.color]="'red'></h3>
<h3 [style]="'background:red;color:blue'">多样式绑定1</h3>
<h3 [style]="{'background' :'red','color':'blue'}">
<!-- 也可以结合三目运算符使用 -->
<h3 [style.font-size]="ok?'21px':'10px'">66666</h3>
3.条件判断是否渲染
(1)如果为真就显示
<div *ngIf="ok">条件判断</div>
在ts中定义ok变量
(2)如果为真就显示1,否则显示2(直接输入ngif else回车即可自动生成)
<!-- 需要安装插件 -->
<ng-container *ngIf="ok; else elseTemplate">
<div>显示1</div>
</ng-container>
<ng-template #elseTemplate>
<div>显示2</div>
</ng-template>
4.循环
(1)for循环
index表示序列,odd是隐式变量
<div *ngFor="let color of colors let i=index let odd=odd">
{{odd}}
{{i}}
{{color}}
</div>
<!-- ts定义的数组 -->
colors=['red','blue','yellow','green']
(2)switch循环
案例:根据type决定渲染那个
<span [ngSwitch]=type>
<p *ngSwitchCase="1">
type=1
</p>
<p *ngSwitchCase="2">
type=2
</p>
<p *ngSwitchDefault>
else
</p>
</span>
<!-- ts声明的type -->
type:number=1;
5.事件绑定/交互
(1)点击事件绑定
<button (click)="clickFun($event)">点击</button>
<!-- event表示事件对象 -->
//在export中写方法
clickFun(e:Event){
console.log(e);
}
(2)绑定input获取输入的值
<!-- 可以绑定input事件 -->
<input type="text" (input)="inputFun($event)">
inputFun(event: any) //注意类型必须用any
{
alert(event.target.value);
}
(3)模板引用变量获取输入的值
<!-- 模板引用变量不仅能绑定输入框,还能引用别的html、或者组件 -->
<input #test type="text">
<button (click)="getTestValue(test.value)">获取输入的值</button>
getTestValue(xxx:string){
alert(xxx);
}
(4)数据双向绑定
<!-- 组件共享值,只对表单元素有效 -->
<!-- 首先需要在app.module.ts引入 -->
import { FormsModule } from '@angular/forms';
<!-- 声明组件需要用到的类 -->
imports: [
BrowserModule,
FormsModule
]
<!-- ts声明变量 -->
title:string='';
<!-- ngmodle只对表单有效,减少modle和controller的交互 -->
<input [(ngModel)]="title" type="text">
<p>{{title}}</p>
(5)响应式表单组件
<!-- 在app.module.ts注册响应式表单模块 -->
import { FormsModule ,ReactiveFormsModule} from '@angular/forms';
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule
]
<!-- 在hello.component.ts导入模块 -->
import { FormControl } from '@angular/forms';
// 注册controller实例
age:FormControl=new FormControl();
<!-- 在hello.component.html中使用 -->
<input type="text" [formControl]="age">
<p>年龄{{age.value}}</p>
<!-- 如果想修改 ,只能通过set方法,不能通过等号-->
ageChangeFun(){
this.age.setValue(18);
}
(5)表单控件分组,例如注册账户需求
<!-- 创建formgroup实例 ,首先引入-->
import { FormControl,FormGroup } from '@angular/forms';
<!-- 声明formgroup实例 -->
loginForm:FormGroup=new FormGroup({
username:new FormControl(''),
password:new FormControl('')
});
<!-- html编写分组表单 -->
<form [formGroup]="loginForm">
<label>账户
<input type="text" formControlName="username">
</label>
<label>密码
<input type="text" formControlName="password">
</label>
</form>
<!-- 获取输入的值 -->
LoginFun(){
console.log(this.loginForm.value)
}
6.表单校验
(1)require关键字(必须写)
<!-- 使用ngmodle做的测试 -->
<!-- 首先在ts中声明变量 -->
formData={
name:'',
password:''
}
<!-- 通过ngmodle获取表单的值,注意使用ngmodle就必须设置name属性 -->
<form>
账户:<input required #nameInf="ngModel" type="text" [(ngModel)]="formData.name" name="username">
<span>{{nameInf.valid}}</span>
密码:<input required #passwordInf="ngModel" type="text" [(ngModel)]="formData.password" name="password">
<!-- <span>{{passwordInf.valid}}</span> -->
<span *ngIf="!nameInf.valid">请输入账户</span>
<button (click)="subFun(nameInf)">提交</button>
</form>
<!-- ts中编写方法,打印组件 -->
subFun(obj:any){
console.log(obj);
}
(2)通过ngmodle跟踪修改状态与有效性验证,根据状态对dom组件绑定状态
已经访问过:ng-touched;没有访问过:ng-untouched
状态修改过:ng-dirty;状态没有修改过:ng-pristine
控件的值有效:ng-valid;控件中没有值:ng-invalid
<!-- 可以根据这个,来对没有输入时,做一些特殊处理 -->
(3)自定义表单验证
<!-- 引入formgroup、formbuilder、validators -->
import { FormControl,FormGroup,FormBuilder,Validators} from '@angular/forms';
<!-- 构造器中注入formbuilder -->
// 注入formbuilder
constructor(private fb:FormBuilder){
}
<!--编写匹配逻辑 -->
valiDataForm=this.fb.group({
username:["",[Validators.required,Validators.maxLength(10),Validators.minLength(5)]],
personID:["",[this.PersonIDVali]]
})
<!-- 自定义方法 ,正则表达式进行匹配-->
PersonIDVali(personID:FormControl):object{
let value=personID.value;
if(!value){
return {'msg':"请输入身份证号码"}
}else{
const vaild=value.match(/\d{17}[\d|x]|\d{15}/);
return vaild ? {}:{'msg':"身份证格式不正确"};
}
}
<!-- dom组件 :可以先打印出组件看看结构再输出-->
<form action="" [formGroup]="valiDataForm">
<label for="">用户名
<input type="text" required formControlName="username">
<p *ngIf="valiDataForm.get('username')?.errors?.['required']">请输入账户</p>
<p *ngIf="valiDataForm.get('username')?.errors?.['minlength']?.requiredLength">用户名长度不正确</p>
<p *ngIf="valiDataForm.get('username')?.errors?.['maxlength']?.requiredLength">用户名长度不正确</p>
</label>
<label for="">身份证号
<input type="text" required formControlName="personID">
<p *ngIf="valiDataForm.get('personID')?.errors">{{valiDataForm.get('personID')?.errors?.['msg']}}</p>
</label>
<button (click)="Fun()">提交</button>
</form>
7.管道
(1)angular内置管道
<!-- 例如大小写字母转换、货币格式转换、日期时间转换 -->
<p>{{date | date:'yyyy-MM-dd HH:mm:ss'}}</p>
<p>{{name | uppercase}}</p>
<p>{{name | lowercase}}</p>
(2)自定义管道
<!-- 执行下面命令,自动创建管道、并且再module.ts文件导入 -->
ng g p 管道名
<!-- 核心在于生成test.pipe.ts中的 transform方法-->
transform(value: unknown, ...args: unknown[]): unknown {
return value+"自定义管道";
}
<!-- 使用和内置的管道一样 -->
<p>{{name | test}}</p>
二、组件交互
1.创建组件与介绍
<!-- 创建组件 -->
ng g c home
(1)生命周期
<!-- 关注三个状态:ngOnchanges()、ngOnInit()、ngDocheck() -->
属性值修改、初始化、销毁
(2)父组件给子组件传值(@Input)
<!-- 在父组件引用子组件时 -->
<app-title [title]="title"></app-title>
<!-- 并且需要在父组件的ts声明要传的title值 -->
<!-- 子组件的ts,使用input装饰器,表示可能接收父组件传的值 -->
@Input()
title?:string
<!-- 然后子组件直接使用就可以 -->
(3)子组件给父组件传值(@Output)
<!-- 父组件 -->
<app-title (addList)="addListFun($event)"></app-title>
<!-- 父组件的ts中编写数组和添加元素的函数 -->
list:number[]=[1,2,3]
addListFun(num:number){
this.list.push(num);
}
<!-- 子组件 通过@output装饰器注册eventemitter-->
@Output() addList=new EventEmitter();
<!-- 向EventEmitter对象中添加数据 -->
PushList(v:string){
this.addList.emit(v);
}
<!-- 这时候子组件调用上面的这个方法就可以向父组件传数据了(类似弹弓弹射的方法) -->
(4)通过@viewChild获取子组件实例,获取子组件数据
<!-- 父组件引用子组件时,给子组件打上标记 -->
<app-title #TitleChild></app-title>
<!-- 使用@viewchild获取子组件 -->
@ViewChild('TitleChild') child:any;
<!-- 这样就可以通过对child+'.'调用子组件的方法和数据 -->
三、服务
服务是声明数据+数据处理逻辑;组件是展示数据的
ng g s 服务名
ng g s server/list
<!-- 服务需要手动导入 -->
<!-- 在modole.t引入 ,并且在providers中注入-->
import { ListService } from './server/list.service';
providers: [ListService]
<!-- 在服务中声明数据,在ts中使用 -->
private list:Array<string>;
constructor() {
this.list=['JAVA','GO','PYTHON'];
}
<!-- 可以提供一些get、set方法 -->
public getlist(){
return this.list;
}
addNode(str:string){
this.list.push(str);
}
<!-- 在组件中使用 -->
<!-- 在component.ts导入,并且在构造器中注入 -->
import { ListService } from './../server/list.service';
constructor(listService:ListService){}
<!-- 通过listService+'.'就可以使用了 -->
四、路由
(1)基础配置
根据url的变化,决定组件的展示
<!-- 执行下面的语句,创建路由配置文件 -->
ng generate module app-routing --flat --module=app
<!-- 在app-routing.module.ts引入组件 -->
import {HomeComponent} from "./home/home.component";
import { HelloComponent } from './hello/hello.component';
import { RouterModule,Routes } from '@angular/router';
<!--设置路由路径对应的组件,路径为空表示上来默认访问的页面 -->
const routes:Routes=[
{
path:'home',
component:HomeComponent
},
{
path:'hello',
component:HelloComponent
}
]
<!-- 说明当前是路由渲染的位置 -->
@NgModule({
declarations: [],
imports: [
CommonModule,
RouterModule.forRoot(routes)
],
exports:[RouterModule]
})
<!--routerLink跳转的路由,routerLinkActive跳转成功绑定的类 -->
<a routerLink="/hello" routerLinkActive="hello">你好</a>
<a routerLink="/home">主页面</a>
<!-- 渲染绑定路由组件的地方 -->
<router-outlet></router-outlet>
(2)路由补充
<!-- 通配符 -->
path:'**',
component:404的component
(3)路由嵌套
<!-- 配置children属性 -->
const routes:Routes=[
{
path:'home',
component:HomeComponent,
children:[
{
path:'list',
component:ListComponent
}
]
}
<!-- 在父路由页面写routerLink和router-outlet-->
<a routerLink="/home/list">跳转到list</a>
<router-outlet></router-outlet>
(4)路由传参
方法一:query方法:使用?拼接
<a routerLink="/hello" [queryParams]="{name:3}">你好</a>
<!-- 通过这种方式获取的值,ts怎么获取? -->
<!-- 构造器注册ActivatedRoute对象 -->
constructor(private routerinfo:ActivatedRoute){}
<!--自动导入 -->
import { ActivatedRoute } from '@angular/router';
<!-- 可以在生命周期函数上进行测试 -->
ngOnInit(): void {
console.log(this.routerinfo.snapshot.queryParams)
<!-- 这是一种常用的获取参数的方式 -->
}
方法二:params方法:使用/拼接
<!-- 在rout文件中拼接参数 -->
{
path:'hello/:id',
component:HelloComponent
}
<!--将参数直接加在routerLink后面 -->
<a [routerLink]="['/hello','111']" [queryParams]="{name:3}">你好</a>
<!-- ts中获取传递的值 -->
id:string='';
ngOnInit(): void {
// console.log(this.routerinfo.snapshot.queryParams)
this.routerinfo.params.subscribe((params:Params)=>{
this.id=params['id']
})
console.log(this.id);
}