【Angular】nvm版本管理_环境配置到入门1016

Angular配置到入门1016

Angular

【速通】三分钟创建一个angular

框架的web

感谢朝夕教育的tina 老师。此笔记在其授课基础上。

1 创建Angular应用:

首先,确保您已经创建了一个Angular应用。如果您还没有创建,请使用Angular CLI(Command Line Interface)来生成一个新的Angular项目:

Copy code
ng new my-app

2 创建组件:

在Angular中,页面通常由组件组成。使用Angular CLI来创建一个新的组件:

Copy code
ng generate component my-component

这将在您的项目中创建一个新的组件,包括HTML、CSS和TypeScript文件。

3 定义路由:

如果您要在应用中导航到不同的页面,您需要设置路由。在Angular中,您可以使用RouterModule来定义应用的路由。在app.module.ts中,导入RouterModule并定义路由配置:

Copy code
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'list', component: ListComponent },
  // 添加其他路由配置
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})

4 在模板中添加路由链接:

在您的应用模板中,您可以使用元素或Angular提供的routerLink指令来创建导航链接。例如:

Copy code
<a [routerLink]="['/list']">Go to List</a>

或使用routerLink指令:

Copy code
<button routerLink="/list">Go to List</button>

5 渲染组件:

当用户点击链接时,Angular会根据路由配置加载并渲染相应的组件。在app.component.html中,您可以使用来指定路由渲染的位置:

Copy code
<router-outlet></router-outlet>

当用户导航到不同的路由,相应的组件将在此处渲染。

6 运行应用:

使用Angular CLI启动您的应用:

Copy code
ng serve

您的应用将运行在本地开发服务器上。通过浏览器访问应用,然后尝试点击不同的链接以查看不同组件的渲染效果。
这些是创建和渲染组件的一般步骤,但根据您的项目需求和复杂性,您可能需要进一步探索Angular的功能,如服务、表单、状态管理等。 Angular的官方文档提供了详细的指南和示例,可帮助您更深入地了解如何构建Angular应用。

【正篇】

1.框架背景

Angular是一个流行的前端开发框架,用于构建现代Web应用程序。以下是有关Angular技术的简要背景介绍:

元素介绍
开发者Angular 是一个由 Google维护的开源JavaScript框架,用于在HTML和JavaScript中构建Web应用程序,是三大框架之首。
Angular 2比较先进,发布于2016年9月份,它是基于ES6来开发的,它的起点更高,整合了现代前端的各种先进理念,在框架、文档、工具等各个层面提供了全方位的支持

架构| Angular采用了一种组件化的架构,其中应用程序被分解为多个可重用的组件。每个组件都有自己的模板、样式和业务逻辑。这种架构有助于开发人员更好地组织和维护代码。
Angular最显著的特征就是其整合性。涵盖了M、V、C/VM等各个层面,不需要组合、评估其它技术就能完成大部分前端开发任务。这样可以有效降低决策成本,提高决策速度,对需要快速起步的团队是非常有帮助的。

TypeScript| Angular使用TypeScript作为主要的开发语言。TypeScript是JavaScript的超集,它添加了静态类型检查和其他有用的功能,帮助开发人员编写更可维护和安全的代码。
双向数据绑定|Angular提供了强大的双向数据绑定机制,允许数据模型和视图之间的自动同步。这意味着当数据模型更改时,视图会自动更新,反之亦然。
指令| Angular引入了一些内置的指令,如ngFor、ngIf、ngSwitch等,以便更轻松地操作DOM元素和控制视图的行为。
依赖注入| 在Angular 中最具特色的就是依赖注入系统,依赖注入是一个重要的概念,用于管理和提供各种依赖项,例如服务、配置、HTTP客户端、路由器等。
路由| Angular的路由模块允许您为应用程序创建多个视图,以实现单页应用程序(SPA)的导航。开发者可以定义路由配置,以确定URL路径与哪个组件相关联。
HTTP客户端| Angular提供了一个HTTP客户端模块,用于进行HTTP请求和处理响应。这对于与后端API交互非常有用。
生命周期钩子| Angular组件具有生命周期钩子,允许您在特定的生命周期事件中执行代码。这些钩子包括ngOnInit、ngOnChanges等。
模块| Angular应用程序通常被组织成多个模块。模块用于管理应用程序的不同部分,使代码更易于维护和协作。
社区和生态系统| Angular拥有庞大的社区和生态系统,包括丰富的第三方库、插件和工具,以及丰富的文档和教育资源。

总之,Angular是一个强大的前端框架,适用于构建大型、复杂的Web应用程序。它提供了丰富的功能和工具,使开发人员能够高效地开发、测试和维护现代Web应用。虽然学习曲线可能较陡,但一旦熟练掌握,Angular可以帮助您构建高质量的Web应用。

2.Angular CLI

2.1 安装

参见

​ Angular CLI用于简单,快速构建Angular2项目,只要掌握几行命令就能扣减前端架构。​


​ # angular报错常见检查

问题原因
刚开机,localhost:4200网络未连接未启动服务器ng serve cd my-app PS C:\code1013\my-app> ng serve
未显示页面语法错误,浏览器无法渲染
语法错误ng+大写
语法错误“” ‘’
语法错误{ ‘[]’ }
语法错误
.ts错误是否写到了{}外面
install安装好后,先ng new my-app创建项目
cd my-app在项目中,启动项目
删除 rm -r src/app/hello-canada然后删除app.module.ts中的引用、配制

<button (click)=“subvaliDataFormFun()”>提交|没有空格导致报错
一定要注意方框 是报错|注意中英文冒号:

addNode() {
this.list.push(‘[Node.js来咯]’)
}
|不需要 ?
nvm 常见命令| nvm list nvm list available

nvm install 版本号 |nvm use 12.21 |||||||||||||||||||

安装和启动angular
//1 版本查询
 PS C:\code1013> ng version

     _                      _                 ____ _     ___                                                                                                 
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|                                                                                                
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |                                                                                                 
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |                                                                                                 
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 8.3.29
Node: 12.22.3
OS: win32 x64
Angular: 
... 

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.803.29
@angular-devkit/core         8.3.29
@angular-devkit/schematics   8.3.29
@schematics/angular          8.3.29
@schematics/update           0.803.29
rxjs                         6.4.0
//2 在项目目录内,启动服务器
PS C:\code1013> ng serve
The serve command requires to be run in an Angular project, but a project definition could not be found.
PS C:\code1013> cd my-app
PS C:\code1013\my-app> ng serve
10% building 3/3 modules 0 active(node:3376) [DEP0131] DeprecationWarning: The legacy HTTP parser is deprecated.
i 「wds」: Project is running at http://localhost:4200/webpack-dev-server/
i 「wds」: webpack output is served from /
i 「wds」: 404s will fallback to //index.html

chunk {main} main.js, main.js.map (main) 55.9 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 269 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 10 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 4.16 MB [initial] [rendered]
Date: 2023-10-16T12:42:33.642Z - Hash: 8702740162ad7fde40fd - Time: 20038ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
i 「wdm」: Compiled successfully.
i 「wdm」: Compiling...
Date: 2023-10-16T12:48:51.804Z - Hash: 22419858fc24793e30f7
4 unchanged chunks
chunk {main} main.js, main.js.map (main) 55.7 kB [initial] [rendered]
Time: 469ms
i 「wdm」: Compiled successfully.
i 「wdm」: Compiling...
i 「wdm」: wait until bundle finished: /runtime.js
i 「wdm」: wait until bundle finished: /polyfills.js
92% additional asset processing copy-webpack-plugini 「wdm」: wait until bundle finished: /styles.js

Date: 2023-10-16T12:48:52.729Z - Hash: 22419858fc24793e30f7
5 unchanged chunks

Time: 483ms
i 「wdm」: Compiled successfully.
//3 服务器启动成功 ,如果网页打不开,首先怀疑项目的语法是否有问题


依赖于NodeJs和npm。
//安装脚手架
npm install -g angular-cli
//创建项目
ng new project_name(项目名称)
//启动项目 在项目目录中启动服务器
cd project_name
ng serve --open 

2.2 主要特性

  1. Angular CLI 可以快速搭建框架,创建module,service,class,directive等;
  2. 具有webpack的功能,代码分割,按需加载;
  3. 代码打包压缩;
  4. 模块测试;
  5. 热部署,有改动立即重新编译,不用刷新浏览器;而且速度很快
    (热部署"(Hot Reloading)是一种开发工具或框架提供的功能,允许您在不需要重启应用程序的情况下进行代码更改并立即看到效果。这对于加快开发周期、提高开发效率和调试非常有用。)
  6. 有开发环境,测试环境,生产环境的配置,不用自己操心;
  7. sass,less的预编译Angular CLI都会自动识别后缀来编译;
  8. typescript的配置,Angular CLI在创建应用时都可以自己配置;
  9. 在创建好的工程也可以做一些个性化的配置,webpack的具体配置还不支持,未来可能会增加;
  10. Angular CLI创建的工程结构是最佳实践,生产可用;
2.3 创建module,component,service,class

3.架构

3.1 模块

​ 模块组件的特征在于可以用于执行单个任务的代码块。 您可以从代码(类)中导出值。 Angular应用程序被称为模块,并使用许多模块构建您的应用程序。 Angular 的基本构建块是可以从模块导出的组件类。

export class AppComponent {
  title = '朝夕教育';
}

3.2 组件

组件是拥有模板的控制器类,主要处理页面上的应用程序和逻辑的视图。 组件可以拥有独立的样式。
注册组件,使用 @Component 注释,可以将应用程序拆分为更小的部分。

3.2.1 ng g c home 创建组件

使用ng命令ng generate component <component-name>创建的组件会自动生成在app.module中的引用,推荐使用ng命令生成组件

//快速创建组件
ng g c xxx
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

@Component最常用的几个选项:

selector:这个 CSS 选择器用于在模板中标记出该指令,并触发该指令的实例化。

template:组件的内联模板

templateUrl:组件模板文件的 URL

styleUrls:组件样式文件

styles:组件内联样式

3.2.2 组件生命周期

组件生命周期、钩子方法

的意义和作用是什么 ,一个小学生,我理解
当我们讨论组件生命周期和钩子方法时,可以把它们想象成是一个小动物的生活过程,比如一只小鸟。让我用这个比喻来解释:

着重从生命周期角度:

项目意义
孵化(Creation)钩子方法中的第一个是 “constructor”(构造函数),就像小鸟孵化出来一样。在这个阶段,小鸟出生了,但它还不会飞,只是一个新生儿。
成长(Growth)接下来是 “ngOnInit”,就像小鸟长大并准备好飞行一样。在这个阶段,小鸟准备好执行一些任务,就像学飞一样。
行动(Action)随后是 “ngOnChanges”,就像小鸟在飞行中改变方向一样。在这个阶段,小鸟可以根据需要改变自己的行为,比如改变飞行方向。
更新(Update)然后是 “ngDoCheck”,就像小鸟在飞行中检查自己的状态一样。在这个阶段,小鸟可以检查自己是否需要进行任何更改。
结束(End)最后是 “ngOnDestroy”,就像小鸟完成飞行并回到巢穴一样。在这个阶段,小鸟完成了它的任务,准备休息。

这些生命周期和钩子方法帮助组件(或小鸟)在不同的时间点执行不同的任务。就像小鸟必须在不同的时间点做不同的事情,Angular组件也需要在不同的时间点执行不同的任务,如准备、执行、检查和结束任务。这有助于组织和管理组件的行为,使它们能够在应用程序中正常工作。



​> 组件生命周期、钩子方法的意义和作用是什么

​组件生命周期和钩子方法在Angular中的意义和作用非常重要,它们用于控制和管理组件在不同时间点的行为和状态。以下是它们的主要作用:

钩子方法意义作用
控制组件行为组件生命周期和钩子方法允许您在组件的生命周期内执行代码,从而控制组件的行为。例如,您可以在初始化时获取数据、在销毁时进行清理、在输入属性发生变化时更新界面等。
实现初始化和清理逻辑ngOnInit和ngOnDestroy等钩子方法可以帮助您在组件创建和销毁时执行必要的初始化和清理逻辑。这对于资源管理(如取消订阅、关闭连接)非常重要,以避免内存泄漏和资源浪费。
处理异步操作钩子方法还可以用于处理异步操作。例如,当组件需要从服务器加载数据时,您可以在ngOnInit中开始加载,以确保数据在界面渲染之前可用。这可以提高用户体验。
响应用户交互钩子方法还可用于响应用户交互。例如,在ngOnChanges钩子中,您可以检查输入属性是否发生变化,并采取相应的行动,如更新组件的显示。
在特定时间点执行代码钩子方法允许您在组件生命周期的特定时间点执行代码。这有助于组织和分解代码,使其更容易维护和理解。

总之,组件生命周期和钩子方法在Angular中的作用是管理和控制组件的行为,确保组件在不同的时间点执行适当的操作。这有助于使代码更清晰、可维护和可扩展,同时提高应用程序的性能和用户体验。理解和熟练使用这些生命周期钩子方法对于有效地开发Angular应用程序非常重要。

​ Angular 会按以下顺序执行钩子方法。你可以用它来执行以下类型的操作。

着重从钩子方法角度:

钩子方法用途时机
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 销毁指令或组件之前立即调用。
3.2.3 组件交互
  1. @Input

    父组件通过`@Input`给子组件绑定属性设置输入类数据
    
    //父组件
    <app-hello  [name]="'tina'"></app-hello>
    
    //子组件
    import { Component, Input } from '@angular/core';
    @Input()
      name!: string;
     ngOnInit(): void {
        console.log(this.name)
      }
    
  2. @Output

    ​ 父组件给子组件传递一个事件,子组件通过@Output弹射触发事件

    //父组件
     <app-hello  (addList)="addListFun($event)"  [name]="'tina'"></app-hello>
     
    list:number[] = [1,2,3,4]
      addListFun(num:number){
        this.list.push(num)
      }
    
    //子组件
    import { Component, Output,EventEmitter } from '@angular/core';
    @Output() addList = new EventEmitter()
      pushList(v:string){
        console.log(this.inpValue)
          this.addList.emit(v)
      }
    
  3. @ViewChild()

    通过`ViewChild`获取子组件实例,获取子组件数据
    
    <app-hello #myChild  [name]="'tina'"></app-hello>
    <button (click)="getView($event)">获取</button>
    
    
    @ViewChild('myChild') child: any;
      constructor() { }
    
      ngOnInit(): void {
      }
      getView(e:any){
        console.log(this.child)
        this.child.setInpValue('我是一段数据')
      }
    
3.3 html模板

在 Angular 中,模板就是一块 HTML。在模板中,你可以通过一种特殊语法来使用 Angular 的许多功能

3.3.1 {{}}插值语法·

​ 所谓 “插值” 是指将表达式嵌入到标记文本中。 默认情况下,插值会用双花括号 {{}} 作为分隔符

<h3>hello {{ name }}</h3>

​ 花括号之间的文本通常是组件属性的名字。Angular 会把这个名字替换为响应组件属性的字符串值

​ 括号间的素材是一个模板表达式我们可以在{{}}内编写js运算

<h3>hello {{ 1+1 }}</h3>
3.3.2 属性绑定
  1. Attribute绑定

    <h3 [id]="'h3-dom'">hello {{ 1+1 }}</h3>
    
  2. 类绑定

    //单一类绑定
    <h3 [class.h3-dom]="true">hello {{ 1+1 }}</h3>
    
    //多重类绑定
    <h3 [class]="'h3-dom title-dom min-title'">hello {{ 1+1 }}</h3>
    <h3 [class]="{'h3-dom':true,'title-dom':false}">hello {{ 1+1 }}</h3>
    <h3 [class]="['h3-dom','title-dom']">hello {{ 1+1 }}</h3>
    
    //ngClass
    export class AppComponent {
        isActive = true;
    }
    
    <h3 [ngClass]="{'active': isActive}">hello {{ 1+1 }}</h3>
    
    
  3. style样式绑定

    //单一样式绑定
    <h3 [style.width]="'300px'">hello {{ 1+1 }}</h3>
    
    //带单位的单一样式绑定
    <h3 [style.width.px]="'300'">hello {{ 1+1 }}</h3>
    
    //多重样式绑定
    <h3 [style]="'background:red;color:#fff'">hello {{ 1+1 }}</h3>
    <h3 [style]="{'background':'red','color':'#fff'}">hello {{ 1+1 }}</h3>
    
    //ngStyle
    export class AppComponent {
        isMax = false;
    }
    <h3 [ngStyle]="{'color': 'red'}">hello {{ 1+1 }}</h3>
    <h3 [ngStyle]="{'font-size': isMax ? '24px' : '12px'}">hello {{ 1+1 }}</h3>
    
【3.3.3】条件判断
  • 类名条件渲染
  1. html
<!-- helloCanada.component.html -->

<h1 [ngClass]="{'h3-dom': true, 'title-dom': false}">类名条件渲染</h1>

  1. css

/* conditional-class.component.css */

.h3-dom {
  font-size: 24px;
  color: blue;
}

.title-dom {
  font-size: 18px;
  color: red;
}

在这里,定义了 ‘h3-dom’ 和 ‘title-dom’ 类的样式。

  1. 添加到任何其他组件的模板中

​ *ngIf是直接影响元素是否被渲染,而非控制元素的显示和隐藏

export class AppComponent {
    isMax = false;
    isMin = false;
}
<div *ngIf="isMax">Max title</div>
<div *ngIf="isMin">Min title</div>

//解析完
<ng-template [ngIf]="isMax">
  <div>Max title</div>
</ng-template>

<ng-container *ngIf="isMax; else elseTemplate">
       isMax为true
</ng-container>
<ng-template #elseTemplate>
    isMax为false
</ng-template>
【3.3.4】 循环语句

​ 解析器会把 let colorlet ilet odd 翻译成命名变量 coloriodd

微语法解析器接收of,会将它的首字母大写(Of),然后加上属性的指令名(ngFor)前缀,它最终生成的名字是 ngFor 的输入属性(colors)

NgFor 指令在列表上循环,每个循环中都会设置和重置它自己的上下文对象上的属性。 这些属性包括 indexodd 以及一个特殊的属性名 $implicit(隐式变量)

Angular 将 let-color 设置为此上下文中 $implicit 属性的值, 它是由 NgFor 用当前迭代中的 colors 初始化的

export class AppComponent {
      colors:Array<string> = [ 'red', 'blue', 'yellow', 'green' ];
}

<div *ngFor="let color of colors let i=index let odd=odd">
  {{odd}}
  {{i}}
  {{color}}
</div>

//解析完
<ng-template ngFor let-color [ngForOf]="colors" let-i="index" let-odd="odd">
  <div>{{odd}} {{i}} {{color}}</div>
</ng-template>
export class AppComponent {
    status = 1;
}

  <ul [ngSwitch]="status">
    <li *ngSwitchCase="1">已支付</li>
    <li *ngSwitchCase="2">订单已经确认</li> 
    <li *ngSwitchCase="3">已发货</li>
    <li *ngSwitchDefault>无效</li>
  </ul>
3.3.5 事件绑定

​ Angular 的事件绑定语法由等号左侧括号内的目标事件名和右侧引号内的模板语句组成。目标事件名是 click ,模板语句是 onSave()

事件对象通过$event传递

export class AppComponent {
   onSave(){
       console.log('点击了按钮')
   }
}

<button 2(click)="onSave($event)">Save</button>
3.3.6 双向绑定

双向绑定是应用中的组件共享数据的一种方式。使用双向绑定绑定来侦听事件并在父组件和子组件之间同步更新值

ngModel指令只对表单元素有效,所以在使用之前需要导入FormsModule板块

import { FormsModule } from '@angular/forms';

@NgModule({
  // 申明组件内用到的视图
  declarations: [
    AppComponent,
    HelloComponent,
  ],
  //引入模块需要的类
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule
  ],
  //全局服务
  providers: [],
  //根组件
  bootstrap: [AppComponent]
})
export class AppComponent {
  userName='';
}
<div>
    输入: <input [(ngModel)]="userName">
	<h1>你输入了: {{userName}}</h1>
</div>
3.3.7 模板引用变量

模板变量可以帮助你在模板的另一部分使用这个部分的数据。使用模板变量,你可以执行某些任务,比如响应用户输入或微调应用的表单

在模板中,要使用井号 # 来声明一个模板变量。下列模板变量 #userName 语法在 <input> 元素上声明了一个名为 userName 的变量

<input #userName placeholder="请输入用户名" />

可以在组件模板中的任何地方引用某个模板变量

<button (click)="callUserName(userName.value)">Call</button>


export class AppComponent {
   callUserName(v){
       console.log(v)
   }
}

Angular 根据你所声明的变量的位置给模板变量赋值:

  • 如果在组件上声明变量,该变量就会引用该组件实例。
  • 如果在标准的 HTML 标记上声明变量,该变量就会引用该元素。
  • 如果你在 <ng-template> 元素上声明变量,该变量就会引用一个 TemplateRef 实例来代表此模板。
3.3.8 表单控件

使用表单控件有三个步骤。

  1. 在你的应用中注册响应式表单模块。该模块声明了一些你要用在响应式表单中的指令。
  2. 生成一个新的 FormControl 实例,并把它保存在组件中。
  3. 在模板中注册这个 FormControl

注册响应式表单模块

要使用响应式表单控件,就要从 @angular/forms 包中导入 ReactiveFormsModule,并把它添加到你的 NgModule 的 imports 数组中。

import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // other imports ...
    ReactiveFormsModule
  ],
})
export class AppModule { }

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

import { Component } from '@angular/core';
import { FormControl } from '@angular/forms';

@Component({
  selector: 'app-name-editor',
  templateUrl: './name-editor.component.html',
  styleUrls: ['./name-editor.component.css']
})
export class NameEditorComponent {
  name = new FormControl('');
}

//使用这种模板绑定语法,把该表单控件注册给了模板中名为 name 的输入元素。这样,表单控件和 DOM 元素就可以互相通讯了:视图会反映模型的变化,模型也会反映视图中的变化

<label>
  Name:
  <input type="text" [formControl]="name">
</label>
<p>


  Value: {{ name.value }}
</p>

修改name值可以通过FormControl 提供的 setValue() 方法

updateName() {
  this.name.setValue('Tina');
}
3.3.9 表单控件分组

表单中通常会包含几个相互关联的控件。响应式表单提供了两种把多个相关控件分组到同一个输入表单中的方法

要将表单组添加到此组件中,请执行以下步骤。

  1. 创建一个 FormGroup 实例。
  2. 把这个 FormGroup 模型关联到视图。
  3. 保存表单数据。

创建一个 FormGroup 实例

在组件类中创建一个名叫 loginForm 的属性,并设置为 FormGroup 的一个新实例。要初始化这个 FormGroup,请为构造函数提供一个由控件组成的对象,对象中的每个名字都要和表单控件的名字一一对应

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

@Component({
  selector: 'app-profile-editor',
  templateUrl: './profile-editor.component.html',
  styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
  loginForm = new FormGroup({
    userName: new FormControl(''),
    password: new FormControl(''),
  });
}

//模板渲染
<form [formGroup]="loginForm">
  
  <label>
    账号:
    <input type="text" formControlName="userName">
  </label>

  <label>
    密码:
    <input type="text" formControlName="password">
  </label>

</form>
3.3.10 表单验证

​ 表单元素添加required关键字表示必填,通过绑定ngModel的引用可以拿到到当前组件的信息,通过引用获取到验证的信息

export class AppComponent {
    fromData={
       name:'',
       password:''
    };

    subBtnFUn(obj){
      console.log(obj)
    }
}

<form  action="">
    账号:<input required #nameInp="ngModel" type="text" [(ngModel)]="fromData.name" name="userName">
    <br>
    <span>{{nameInp.valid }}</span>
    <hr>
    密码:<input required  #pasInp="ngModel" type="text" [(ngModel)]="fromData.password" name="password">
    <br>
    <span>{{pasInp.valid }}</span>
    <hr>
    <button (click)="subBtnFUn(nameInp)">提交</button>
</form>

我们还可以通过 ngModel 跟踪修改状态与有效性验证,它使用了三个 CSS 类来更新控件,以便反映当前状态。

状态为 true 时的类为 false 时的类
控件已经被访问过ng-touchedng-untouched
控件值已经变化ng-dirtyng-pristine
控件值是有效的ng-validng-invalid
3.3.11 自定义表单验证

​ 先引入表单的一些内置依赖

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

//构造函数里注入FormBuilder
constructor(private fb:FormBuilder) { }

//错误提醒数据
formErrors = {
  'title': '',
  'content': ''
};


//在组件类的初始化函数里对表单中的元素的校验进行定义,并调用表单的valueChanges方法,检测表单的输入的变化
ngOnInit():void {
  this.taskInfo.isComplete = 1;
  this.tasksForm = this.fb.group({
     userName: ['', [Validators.required,
    				 Validators.maxLength(18),
                     Validators.minLength(6) ] ],
    password: ['', [this.passWordVal]],
    phone: ['', [Validators.required,this.phoneVal],]
  });

  phoneVal(phone: FormControl): object {
    const value = phone.value || '';
    if(!value) return  {desc:'请输入手机号'}
    const valid =  /[0-9]{11}/.test(value);
    return valid ? {} :{desc:'联系电话必须是11位数字'}
  }
  passWordVal(password:FormControl):object{
    const value = password.value || '';
    const valid = value.match(/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/);
    return valid ? {} : {passwordValidator: {desc:'密码至少包含 数字和英文,长度6-20'}}
  }
}
3.3.12 管道

​ 管道的作用就是传输。不同的管道具有不同的作用。(其实就是处理数据)

angular中自带的pipe函数

管道功能
DatePipe日期管道,格式化日期
JsonPipe将输入数据对象经过JSON.stringify()方法转换后输出对象的字符串
UpperCasePipe将文本所有小写字母转换成大写字母
LowerCasePipe将文本所有大写字母转换成小写字母
DecimalPipe将数值按照特定的格式显示文本
CurrentcyPipe将数值进行货币格式化处理
SlicePipe将数组或者字符串裁剪成新子集
PercentPipe将数值转百分比格式

pipe用法

  • {{ 输入数据 | 管道 : 管道参数}} (其中‘|’是管道操作符)

  • 链式管道 {{ 输入数据 | date | uppercase}}

  • 管道流通方向自左向右,逐层执行

    使用脚手架命令:ng g p test

    import { Pipe, PipeTransform } from '@angular/core';
    
    @Pipe({
      name: 'testTitle'
    })
    export class TestPipe implements PipeTransform {
    
      transform(value: unknown, ...args: unknown[]): unknown {
        console.log(value)
        return 'title';
      }
    }
    
    
    <p>{{ 'Angular' | testTitle }}</p>
    
    
3.4 服务

angular中,把从组件内抽离出来的代码叫服务,服务的本质就是函数

官方认为组件不应该直接获取或保存数据, 它们应该聚焦于展示数据,而把数据访问的职责委托给某个服务。而服务就充当着数据访问,逻辑处理的功能。把组件和服务区分开,以提高模块性和复用性。通过把组件中和视图有关的功能与其他类型的处理分离开,可以让组件类更加精简、高效。

使用命令ng g s xxx创建一个服务,通过**@Injectable()**装饰器标识服务。

//导入Injectable装饰器
import { Injectable } from '@angular/core';
//使用Injectable装饰器声明服务
@Injectable({
  //作用域设定,'root'表示默认注入,注入到AppModule里
  providedIn: 'root',
})
export class TestService {
}

组件中如何使用服务呢,必须将服务依赖注入系统、组件或者模块,才能够使用服务。我们可以用注册提供商根注入器实现**。**

该服务本身是 CLI 创建的一个类,并且加上了 @Injectable() 装饰器。默认情况下,该装饰器是用 providedIn 属性进行配置的,它会为该服务创建一个提供商。

3.5 依赖注入

​ 在这个例子中,providedIn: 'root' 指定 Angular 应该在根注入器中提供该服务,从而实现根注入器将服务注入,它就在整个应用程序中可用了**。**

providedIn

​ ‘root’ :注入到AppModule,提供该服务,所有子组件都可以使用(推荐)

​ null : 不设定服务作用域(不推荐)

​ 组件名:只作用于该组件(懒加载模式)


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class TestService {
}


import { Component, OnInit } from '@angular/core';
import {HeroService} from '../hero.service'

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss'],
})
export class TestComponent implements OnInit {

  constructor(private heroService:HeroService) { }

  ngOnInit(): void {
    console.log(this.heroService.getHeroList())
  }
}

​ 也可以使用 @Component@Directive 内部的 providers: [],为特定的组件子树提供服务,这也将导致创建多个服务实例(每个组件使用一个服务实例)


import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class TestService {
}


import { Component, OnInit } from '@angular/core';
import {HeroService} from '../hero.service'

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss'],
  providers: [HeroService]
})
export class TestComponent implements OnInit {

  constructor(private heroService:HeroService) { }

  ngOnInit(): void {
    console.log(this.heroService.getHeroList())
  }
}
3.6 路由

​ 路由就是连接组件的筋络,它也是树形结构的.有了它,就可以在angular中实现路径的导航模式

可以把路由看成是一组规则,它决定了url的变化对应着哪一种状态,具体表现就是不同视图的切换

在angular中,路由是非常重要的组成部分, 组件的实例化与销毁,模块的加载,组件的某些生命周期钩子的发起,都是与它有关

3.6.1 路由基本使用

路由器是一个调度中心,它是一套规则的列表,能够查询当前URL对应的规则,并呈现出相应的视图.

路由是列表里面的一个规则,即路由定义,它有很多功能字段:

  • path字段,表示该路由中的URL路径部分
  • Component字段,表示与该路由相关联的组件

每个带路由的Angular应用都有一个路由器服务的单例对象,通过路由定义的列表进行配置后使用。

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from './home/home.component'

const routes: Routes = [
 {path:'home',component:HomeComponent}
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

//路由导航 
<a [routerLink]="['/home']">home</a>
 <a [routerLink]="['/hello']">hello</a>

//组件渲染输出
<router-outlet></router-outlet>

上述具体的工作流程,可以举例简单描述为:

  • 当浏览器地址栏的URL变化时,路径部分/home满足了列表中path为"home"的这个路由定义,激活对应HomeComponent的实例,显示它的视图
  • 当应用程序请求导航到路径/hello时,符合了另外的规则,激活对应视图且展示内容,并将该路径更新到浏览器地址栏和历史
3.6.2 路由嵌套

​ 父子路由嵌套配置:

const routes: Routes = [
    {path:'home',
      component:HomeComponent,
      children:[
        {path:'hello',component:HelloComponent}
      ]
    },
];

​ 在home Component内这是router-outlet路由出口,即可在home 路由内渲染子级路由

//home template
<h2>home Component</h2>
<a [routerLink]="['/home/hello']">hello</a>
<router-outlet></router-outlet>

​ 在非home Component内跳转到/home/hello路由需要写全路径

//app template
<h2>app Component</h2>
<a [routerLink]="['/home/hello']">hello</a>
<router-outlet></router-outlet>

3.6.3 路由传参
  • query

    在a标签上添加一个参数queryParams,并通过this.routerinfo.snapshot.queryParams获取参数

    <a [routerLink]="['/hello']" [queryParams]="{id:3}" >hello</a>
    
    import {ActivatedRoute} from '@angular/router';
    constructor(private routerinfo:ActivatedRoute) { }
    
     ngOnInit() {
      //id为参数名字
        this.id=this.routerinfo.snapshot.queryParams["id"]
      }
    
  • params

    修改路由配置文件path,路由导航a标签routerLink后面数组的第二个参数为传递的值

    并且通过subscribe请阅的方式获取name参数

     {
        path: 'hello/:name',
        component:HelloComponent,
      },
    
    //我们在后面添加/:name此时name即为传递的参数名字
    //a标签设置如下
    <a [routerLink]="['/hello','我是url传递参数']" [queryParams]="{id:3}" >hello</a>
    
    ngOnInit() {
        this.routerinfo.params.subscribe((params:Params)=>{
          this.name=params['name']
        })
      }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值