Besoin d'accéder directement aux paramètres, principalement pour obtenir la valeur initiale
, utilisez snapshot si aucun abonnement n'est requis 🎜🎜🎜route.params.subscribe():🎜 ;- 参数每次变化都要获取到或者需要连续导航多次的时候的用params;
Router
是一个提供导航和操纵URL的模块,具体提供的方法可参照Router官网,开发中常用到的方法如下,具体讲解在路由传参中会详细介绍:
1 2 | import { Router } from '@angular/router';
|
Copier après la connexion
Copier après la connexion
路由传参以及获取
路由传参的两种形式
1. params (是/:id 动态路由)
使用场景: 比如当我们点击商品列表链接时,希望把用户信息,或者商品种类信息通过url,传到商品列表的组件中去。
1 2 3 4 5 6 7 | const routes: Routes = [
{
path: 'goodsList/:id',
component: GoodsListComponent,
},
];
|
Copier après la connexion
Copier après la connexion
2. queryParams(是?id=xx 形式)
使用场景: 当我们希望通过url传递多个参数的时候,可以选择用这种方式进行路由传参
1个参数可以优先用动态路由,2个以上还是用query更加方便点
路由中传参的3种具体方法
1. routerLink
单一参数:
1 2 3 | <a [routerLink]= "['/goodsList', id]" routerLinkActive= "active-class" >切换到商品列表组件</a>
|
Copier après la connexion
Copier après la connexion
多个参数:
1 2 | <a [routerLink]= "['/personalCenter']" [queryParams]= "{name: 'zs', age: 16}" >切换到个人中心组件</a>
|
Copier après la connexion
Copier après la connexion
routerLinkActive
跟踪元素上链路路由当前是否处于活动状态
。并允许你指定一个或者多个css类,以便在链接路由处于活动状态时添加该元素。
2. router.navigate
基于所提供的命令数组和起点路由进行导航。 如果没有指定起点路由,则从根路由开始进行绝对导航
单一参数:
1 2 3 4 5 6 7 8 9 | public goToGoodsListPage(): void {
this._router.navigate([`/goodsList/${this.id}`]);
this._router.navigate(['/goodsList', this.id]);
}
<button (click)= "goToGoodsListPage()" >切换到商品列表组件</button>
|
Copier après la connexion
多个参数:
1 2 3 4 5 6 | public goToPersonalCenterPage(): void {
this._router.navigate(['/personalCenter'], {queryParams:{name: 'zs', age: 16}});
}
<button (click)= "goToPersonalCenterPage()" >切换到个人中心组件</button>
|
Copier après la connexion
3. router.navigateByUrl
基于所提供的 URL 进行导航,必须使用绝对路径
。对于单一参数和多个参数的使用方法与router.navigate一致。
1 2 3 4 5 | public goToPersonalCenterPage(): void {
this._router.navigateByUrl(`/personalCenter?name=zs&age=16`);
}
|
Copier après la connexion
在路由中接收参数的2种方式
1. 接收params类型的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 | import { ActivatedRoute } from '@angular/router';
constructor(
private _route: ActivatedRoute,
) {}
public ngOnInit(): void {
const param = this.route.snapshot.params;
this.route.params.subscribe(params => {
console.log(params);
});
}
|
Copier après la connexion
2. 接收queryParams类型的参数
1 2 3 4 5 6 7 8 9 10 11 12 13 | import { ActivatedRoute } from '@angular/router';
constructor(
private _route: ActivatedRoute,
) {}
public ngOnInit(): void {
const queryParam = this.route.snapshot.queryParams;
this.route.queryParams.subscribe(params => {
console.log(params);
});
}
|
Copier après la connexion
路由重定向
应用场景:当在一个应用中,希望用户默认跳转到某个页面时,就需要使用得到路由重定向。
重定向的组成:
- 使用重定向源的path
- 重定向目标的component
- pathMatch值来配置路由
1 2 3 | { path: '',
redirectTo: '/personalCenter',
pathMatch: 'full' },
|
Copier après la connexion
pathMatch是一个用来指定路由匹配策略的字符串。可选项有 prefix(默认值)和 full。
prefix: 以指定的路径开头 (就是path中的值与用户输入的的开头路径是一样的,比如path是”abc“,那么用户输入/abc, /abc/a都是可以的,但是输入 /abcd这样就不可以); 如果path是空,那么所有路由都会匹配到这个页面上
full: 与指定路径完全一样(这个就要求与path要求的路径完全一样,比如说path是‘abc’,那么用户输入/abc , /abc/是可以的 /abcd,/abc/d是不可以的); 如果path是空,那么只有localhost:4200后边什么都不加的情况下才匹配到这个页面上。
路由顺序
Router在匹配路由的时候,使用的是”先到先得“的策略,所以应当将具体的静态的路由放前边,然后可以放置默认路由匹配的空路径路由,通配符路由是最后一个(他可以匹配所以路由,当其他路由都没有匹配对的时候,Router才会选择他)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | const routes: Routes = [
{
path: 'goodsList/:id',
component: GoodsListComponent,
},
{
path: 'personalCenter',
component: PersonalCenterComponent,
},
{
path: '',
redirectTo: '/personalCenter',
pathMatch: 'full'
},
{ path: '**', component: PageNotFoundComponent },
];
|
Copier après la connexion
路由嵌套
Lorsque l'application devient complexe, vous devrez peut-être créer des routes relatives en dehors du composant racine, et ces routes deviennent des sous-routes, ce qui signifie que vous devez en ajouter une seconde out let>, parce que c'est un autre {} < routero ut le t> ;.
场景: 我们需要在个人中心的页面中,跳转到他的两个子页面中,分别是个人配置页面和个人详情页面,具体代码实现如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { GoodsListComponent } from './goods-list/goods-list.component';
import { PersonalCenterComponent } from './personal-center/personal-center.component';
import { PersonalSettingComponent } from './personal-setting/personal-setting.component';
import { PersonalDetailComponent } from './personal-detail/personal-detail.component';
const routes: Routes = [
{
path: 'goodsList/:id',
component: GoodsListComponent,
},
{
path: 'personalCenter',
component: PersonalCenterComponent,
children: [
{
path: 'personalDetail',
component: PersonalDetailComponent,
},
{
path: 'personalSetting',
component: PersonalSettingComponent,
},
]
},
{
path: '',
redirectTo: '/personalCenter',
pathMatch: 'full'
},
];
<div class = "personal-center-container" >
这是个人中心页面
<a routerLink= "./personalDetail" >切换个人详情页面</a>
<a routerLink= "./personalSetting" >切换到个人配置页面</a>
</div>
<router-outlet></router-outlet>
|
Copier après la connexion
子路由和其它路由一样,同时需要 path 和 component。唯一的区别是你要把子路由放在父路由的 children
数组中。
路由懒加载
你可以配置路由定义来实现惰性加载模块,这意味着 Angular只会在需要时才加载这些模块,而不是在应用启动时就加载全部。
1、先给之前的两个页面组件增加一个module文件,然后routes中使用loadChildren代替component进行配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
const routes: Routes = [
{
path: 'goodsList/:id',
loadChildren: () => import('./goods-list/goods-list.module')
.then(m => m.GoodListModule)
},
{
path: 'personalCenter',
loadChildren: () => import('./personal-center/personal-center.module')
.then(m => m.PersonalCenterModule)
},
{
path: '',
redirectTo: '/personalCenter',
pathMatch: 'full'
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
|
Copier après la connexion
2、在之前的两个页面组件中添加路由模块文件,添加一个指向该组件的路由。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { GoodsListComponent } from './goods-list.component';
const routes: Routes = [
{
path: '',
component: GoodsListComponent
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class GoodsListRoutingModule { }
|
Copier après la connexion
路由守卫(仅了解)
使用路由守卫来防止用户未经授权就导航到应用的某些部分,想了解更多请移步 路由守卫官网介绍
- 用CanActivate来处理导航到某路由的情况。 // 进入路由的时候
- 用CanActivateChild来处理导航到某子路由的情况。
- 用CanDeactivate来处理从当前路由离开的情况. // 离开路由的时候
- 用Resolve在路由激活之前获取路由数据。
- 用CanLoad来处理异步导航到某特性模块的情况。CanActivate仍然会加载某个模块,canload不会去加载当不满足条件的情况下
1 2 3 4 5 6 7 | export class TestGuard implements CanActivate {
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
}
}
|
Copier après la connexion
1 2 3 4 5 | {
path: 'test-path',
component: TestComponent,
canActivate: [TestGuard],
}
|
Copier après la connexion
路由事件(仅了解)
Router 在每次导航过程中都会通过 Router.events 属性发出导航事件。这些事件的范围贯穿从导航开始和结束之间的多个时间点。想了解更多请移步
路由事件官网详细介绍
https://angular.cn/guide/router-reference#router-events
Introduction aux formulaires dans Angular
La différence entre les formulaires réactifs et les formulaires basés sur des modèles
| Formule réactive | Modèle entraîné |
---|
pour créer un modèle de forme | explicitement, créé dans la classe des composants | implicitement, avec des instructions pour créer |
Modèle de données | Structuré et immuable (objet observable) | Non structuré et mutable (liaison bidirectionnelle de données) |
Flux de données | Synchrone | Asynchrone |
Validation de formulaire | Fonctions | Directives |
常用表单公共基础类
响应式表单和模板驱动表单都建立在下列基础类之上。
FormControl 实例用于追踪单个表单控件的值和验证状态。
FormGroup 用于追踪一个表单控件组的值和状态。
FormArray 用于追踪表单控件数组的值和状态。(了解)
模板驱动表单
依赖模板中的指令来创建和操作底层的对象模型。主要用于添加简单的表单,使用起来较简单,但是扩展性方面不如响应式表单。当控件值更新的时候相关的属性值会被修改为新值。
创建表单
1 2 3 4 5 6 7 8 9 10 11 | <!-- #form是模板引用变量,他就代表是form整个元素,我们可以在当前模板的任何地方使用模板引用变量。-->
<!-- 这些变量提供了从模块中直接访问元素的能力 -->
<!-- name名称一定要加上 因为表单中的所有组件和控件都应该有名称-->
<form (ngSubmit)= "onSubmit(myform.value);" #myform= "ngForm" novalidate>
<label for = "name" >姓名: </label>
<input type= "text" name= "name" [(ngModel)]= "name" >
<label for = "password" >密码: </label>
<input type= "password" name= "password" [(ngModel)]= "password" >
<button>提交</button>
</form>
|
Copier après la connexion
模板驱动表单中验证输入
1 2 3 4 5 6 7 8 9 10 11 12 | <!--假如我们希望给上述的表单做个校验,密码不能为空,名字的长度不能少于2个字符-->
<form (ngSubmit)= "onSubmit(myform);" #myform= "ngForm" >
<label for = "name" >姓名: </label>
<input type= "text" name= "name" [(ngModel)]= "name" minlength= "2" >
<label for = "password" >密码: </label>
<input type= "password" name= "password" [(ngModel)]= "password" required>
<button>提交</button>
<!-- 主要通过hasError方法来实现-->
<div *ngIf= "myform.form.hasError('minlength', 'name')" >姓名的长度不能少于2位</div>
<div *ngIf= "myform.form.hasError('required', 'password')" >密码不能为空</div>
</form>
|
Copier après la connexion
响应式表单(重点)
提供对底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮,它们的可扩展性、可复用性和可测试性都更高。而且控件更新的效率更高,因为FormControl 的实例总会返回一个新值,而不会更新现有的数据模型,如果表单是你的应用程序的关键部分,或者可扩展性很强,那就使用响应式表单
使用响应式表单
1、在模块文件中引入响应式表单模块
1 | import { ReactiveFormsModule } from '@angular/forms';
|
Copier après la connexion
2、在组件中引入表单组
1 | import { FormGroup, FormControl } from '@angular/forms';
|
Copier après la connexion
3、创建一个FormGroup实例,并把这个FormGroup模型关联到视图
1 2 3 4 | this.profileForm = new FormGroup({
name: new FormControl(''),
password: new FormControl(''),
});
|
Copier après la connexion
1 2 3 4 5 6 7 8 | <form [formGroup]= "profileForm" (ngSubmit)= "submitForm(profileForm.value)" >
<label for = "name" >First Name: </label>
<input id= "name" type= "text" formControlName= "name" >
<label for = "password" >Last Name: </label>
<input id= "password" type= "text" formControlName= "password" >
<button>提交</button>
</form>
|
Copier après la connexion
表单嵌套
表单组可以同时接受单个表单控件实例和其它表单组实例作为其子控件。这可以让复杂的表单模型更容易维护,并在逻辑上把它们分组到一起。
1、创建一个嵌套的表单组。
1 2 3 4 5 6 7 8 9 | this.profileForm = new FormGroup({
name: new FormControl('', [Validators.required]),
password: new FormControl(''),
address: new FormGroup({
street: new FormControl(''),
city: new FormControl(''),
})
});
|
Copier après la connexion
2、在模板中对这个嵌套表单分组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <form [formGroup]= "profileForm" (ngSubmit)= "submitForm(profileForm.value)" >
<label for = "name" >First Name: </label>
<input id= "name" type= "text" formControlName= "name" >
<label for = "password" >Last Name: </label>
<input id= "password" type= "text" formControlName= "password" >
<div formGroupName= "address" >
<h3>Address</h3>
<label for = "street" >Street: </label>
<input id= "street" type= "text" formControlName= "street" >
<label for = "city" >City: </label>
<input id= "city" type= "text" formControlName= "city" >
</div>
<button>提交</button>
</form>
|
Copier après la connexion
表单验证
控件状态的字段
在学习表单验证之前,我们先来了解一下angular针对表单所提供的一些状态字段,这些字段可帮助用户决定在那些阶段去做表单验证。
用来判断用户是否获取过焦点
,如果获取过焦点则touched=true; untouched=false,如果从来没有获取过焦点,touched=false; untouched=true。
用来判断用户是否操作过字段
,dirty表示用户操作过表单元素,pristine表示未操作过表单元素。
判断表单元素是否有效
,当表单元素上有多个验证条件事,只有所有的验证条件都满足验证要求valid才是true,只要有一个验证条件不满足,那么invalid这个属性值就是true。
控件状态的CSS 类
Angular 会自动把很多控件属性作为 CSS类映射到控件所在的元素上。你可以使用这些类来根据表单 状态给表单控件元素添加样式。
- .ng-valid
- .ng-invalid
- .ng-pending
- .ng-pristine
- .ng-dirty
- .ng-untouched
- .ng-touched
场景: 比如我们希望当控件在不满足验证条件的情况下,控件边框显示成红色~ 实现方式如下:
1 2 3 4 5 | .ng-touched:not(form){
&.ng-invalid:not(form){
border: 1px solid red
}
}
|
Copier après la connexion
表单验证的步骤
1、在表单组件中导入一个验证器函数,Angular具体提供了那些内置验证器请参照表单验证器官网
1 2 | import { Validators } from '@angular/forms';
|
Copier après la connexion
2、把这个验证器添加到表单中的相应字段。
场景:需要做验证的内容分别是,① 名称不能为空; ② 密码不能为空,且最小长度不能少于4; ③住址中的街道不能为空
1 2 3 4 5 6 7 8 | this.profileForm = new FormGroup({
name: new FormControl('', [Validators.required]),
password: new FormControl('', [Validators.required, Validators.minLength(4)]),
address: new FormGroup({
street: new FormControl('', [Validators.required]),
city: new FormControl(''),
})
});
|
Copier après la connexion
3、在模板中错误信息的提醒逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <form [formGroup]= "profileForm" (ngSubmit)= "submitForm(profileForm.value)" >
<!-- 姓名-->
<label for = "name" >姓名: </label>
<input id= "name" type= "text" formControlName= "name" >
<div [hidden]= "profileForm?.get('name').valid || profileForm?.get('name')?.untouched" >
<p [hidden]= "!profileForm.hasError('required', 'name')" >名字是必填项</p>
</div>
<!-- 密码-->
<label for = "password" >密码: </label>
<input id= "password" type= "text" formControlName= "password" >
<!-- 先验证密码当密码是合法的或者用户从未操作多的时候,不显示错误信息 -->
<!-- 然后在根据hasError来判断具体的错误提醒-->
<div [hidden]= "profileForm?.get('password').valid || profileForm?.get('password')?.untouched" >
<p [hidden]= "!profileForm.hasError('minlength', 'password')" >密码的位数不能少于四位</p>
<p [hidden]= "!profileForm.hasError('required', 'password')" >密码不能为空</p>
</div>
<!-- 地址表单组-->
<div formGroupName= "address" >
<h3>Address</h3>
<label for = "street" >Street: </label>
<input id= "street" type= "text" formControlName= "street" >
<div [hidden]= "profileForm?.get('address')?.get('street')?.valid || profileForm?.get('address')?.get('street')?.untouched" >
<div [hidden]= "!profileForm.hasError('required', ['address', 'street'])" >街道不能为空</div>
</div>
<label for = "city" >City: </label>
<input id= "city" type= "text" formControlName= "city" >
</div>
<button>提交</button>
</form>
|
Copier après la connexion
自定义表单验证器
场景: 用户希望在填写手机号的时候,可以验证手机号的格式是否输入正确,便可以通过自定义函数去做这件事
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public ngOnInit(): void {
this.profileForm = new FormGroup({
phone: new FormControl('', [this.mobileValidator])
});
}
public mobileValidator = (control: FormControl): any => {
const value = control.value;
const mobileReg = /^0?(13[0-9]|15[012356789]|17[013678]|18[0-9]|14[57])[0-9]{8}$/;
const result = mobileReg.test(value);
return result ? null : {mobileFormat: {info: '手机格式不正确'}};
}
<form [formGroup]= "profileForm" (ngSubmit)= "submitForm(profileForm.value)" >
<input id= "phone" type= "text" formControlName= "phone" >
<div>{{profileForm?.get('phone').errors | json}}</div>
<div [hidden]= "profileForm?.get('phone').valid || profileForm?.get('phone')?.untouched" >
<p [hidden]= "!profileForm.hasError('mobileFormat', 'phone')" >手机格式不正确</p>
</div>
<button>提交</button>
</form>
|
Copier après la connexion
如何更新表单数据
- 使用
setValue()
方法来为单个控件设置新值。 setValue() 方法会严格遵循表单组的结构,并整体性
替换控件的值。 - 使用
patchValue()
方法可以用对象中所定义的任何属性为表单模型进行替换。
使用FormBuilder服务生成控件
FormBuilder 服务提供了一些便捷方法来生成表单控件。FormBuilder 在幕后也使用同样的方式来创建和返回这些实例,只是用起来更简单。
服务有三个方法:control()、group() 和 array()。这些方法都是工厂方法,用于在组件类中分别生成 FormControl、FormGroup 和 FormArray。
1.在组件中引入FormBuilder类,并注入服务
1 2 | import { FormBuilder } from '@angular/forms';
constructor( private fb: FormBuilder) { }
|
Copier après la connexion
2.生成表单内容
1 2 3 4 5 6 7 8 9 10 11 | this.profileForm = this.fb.group({
name: [''],
password: ['']
});
this.profileForm = new FormGroup({
name: new FormControl(''),
password: new FormControl(''),
});
|
Copier après la connexion
跨字段交叉验证(仅了解)
1 2 3 4 5 6 7 8 9 10 11 12 13 | const heroForm = new FormGroup({
'name': new FormControl(),
'alterEgo': new FormControl(),
'power': new FormControl()
}, { validators: identityRevealedValidator });
export const identityRevealedValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
const name = control.get('name');
const alterEgo = control.get('alterEgo');
return name && alterEgo && name.value === alterEgo.value ? { identityRevealed: true } : null;
};
|
Copier après la connexion
更多编程相关知识,请访问:编程视频!!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!