angular.js

161 阅读7分钟

项目目录介绍

image.png

编写Hello world

  1. 在app文件夹下,新建一个组件文件,文件名为hello-world.component.ts image.png

从上图片中,我们可以得知组件的组成有以下三部分组成

  • (类名的命名是根据组件的文件名来决定的,首字母大写的驼峰命名方式)

  • 装饰器@component, 需要从'@angular/core'中导入,其作用是把某个类标记为Angular组件,并为他配置一些元数据,目前这里只涉及到3个元数据,其中selector也称作是选择器,我们可以把他理解成我们自定义组件的名字,一般他的命名也是app-组件文件的名字,更多的元数据应用可以参照官网。

  • HTML模板,就是template。

  1. 上边已经提到,组件必须在模块中声明才可以正常使用,所以我在根模块声明一下

image.png

  1. 我们将定义好的组件在app的html中引用一下

image.png

组件中值的传递

子传父

// app-outside-introduction是app.component的子组件,现在通过这个组件来学习一下父子传值

// outside-introduction.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-outside-introduction',
  templateUrl: './outside-introduction.component.html',
  styleUrls: ['./outside-introduction.component.scss']
})

export class OutsideIntroductionComponent {
 // @Input()是专门用来实现传值的,需要提前在'@angular/core引入
 // 这句声明,表示希望在父组件引入子组件的html页面中,从父组件中传入一个值给到showNumber
  @Input() public showNumber: number;
}

// outside-introduction.component.html
<div>显示父组件传进来的值{{showNumber}}</div>
// 父组件app.component.html
<div>父组件中的值:{{defaultNum}}</div>
<app-outside-introduction [showNumber]="defaultNum"></app-outside-introduction>

// 父组件app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  public defaultNum = 5;
}

父传子

子组件向父组件传值,通过事件的形式来实现

// 子组件

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-outside-introduction',
  templateUrl: './outside-introduction.component.html',
  styleUrls: ['./outside-introduction.component.scss']
})

export class OutsideIntroductionComponent {
  @Input() public showNumber: number;
  // 下边的逻辑主要实现自组价向父组件emit一个值
  @Output() public curCountChange = new EventEmitter<number>();
  public curCount = 1;
  public addCount(): void {
    this.curCount++;
    this.curCountChange.emit(this.curCount);
  }
}
// 父组件

// 这里的事件名curCountChange必须和子组件定义@Output()的名字是一样的,=后边的方法名可以自己随意定义
// `$event`是子组件传过来的值
<app-outside-introduction [showNumber]="defaultNum" (curCountChange)="handlCurCountChange($event)"></app-outside-introduction>

  public handlCurCountChange(value: number): void {
    // 这里的value就是子组件传过来的值
    this.valueFromChild = value;
  }
  • @Output() - 一个装饰器函数,它把该属性标记为数据从子组件进入父组件的一种途径

  • curCountChange - 这个 @Output() 的名字

  • EventEmitter<number> - 这个 @Output() 的类型,就是子组件传给父组件的数据类型

  • new EventEmitter<number>() - 使用 Angular 来创建一个新的事件发射器,它发出的数据是 number 类型的。

  • curCountChange.emit() - 通过emit方法来向父组件传递值 最终父组件通过事件的形式接受子组件穿过来的值

组件的生命周期

Angular组件中生命周期共有九个,常用的有三到四个

路由

1.创建路由

import { NgModule } from '@angular/core';
// 引入路由模块 RouterModule和 Routes
import { Routes, RouterModule } from '@angular/router'; 
// 引入在不同URL下,需要展示的组件
import { GoodsListComponent } from './goods-list/goods-list.component';
import { PersonalCenterComponent } from './personal-center/personal-center.component';

// 配置的路由数组
const routes: Routes = [
  {
    path: 'goodsList', // 定义路由名称
    component: GoodsListComponent, // 指定显示的那个组件
  },
  {
    path: 'personalCenter', // 定义路由名称
    component: PersonalCenterComponent, // 指定显示的那个组件
  }
];

@NgModule({
   // forRoot() 方法会创建一个 NgModule,其中包含所有指令、给定的路由以及 Router 服务本身。
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}
  1. 在app.module.ts中导入AppRoutingModule
import { AppRoutingModule } from './app-routing.module';
  1. 在app.component.html中把这些路由添加进来,以便控制导航的展示
 <div class="route-change-container">
  <a routerLink="/goodsList">切换到商品列表组件</a> <!--routerLink将你定义的路由连接到模板文件中-->
  <a routerLink="/personalCenter">切换到个人中心组件</a>
</div>

<router-outlet></router-outlet>  <!--此指令通过路由来动态加载组件-->

ActivatedRoute

用于获取路由信息

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; // ① 先引入ActivatedRoute

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

  constructor(
      private route: ActivatedRoute, //依赖注入这个服务
  ) {}

 // 在初始化的生命周期中去获取url的路由信息
  public ngOnInit(): void {
    // 第一种获取参数的方式
    const params = this.route.snapshot.params;
    
    // 第二种获取参数的方式
    this.route.params.subscribe(params => {
      console.log(params);
    });
  }

}

Router

是一个提供导航和操纵URL提供导航和操纵URL的模块,使用前需要引入

  1. navigate()  该方法支持的参数类型和routerLink指令一样,所以他们的作用也是一样的;
  2. navigateByUrl()  该方法支持绝对路由;

路由传参俩种形式

  1. params (是/:id 动态路由)
  2. queryParams(是?id=xx 形式)

路由传参三种方法

  1. routerLink 单一参数
 <a [routerLink]="['/goodsList', id]" routerLinkActive="active-class">切换到商品列表组件</a>
 // 其中/goodsListl是我设置的路由path,id是需要传递的参数   
 // 多个参数的时候,也可以用这种形式,只不过看起来不够直观,所以不推荐多个参数的时候也用这种方法

多个参数

 <a [routerLink]="['/personalCenter']" [queryParams]="{name: 'zs', age: 16}">切换到个人中心组件</a>
 // 参数的格式可以自行组织成各种object
  1. router.navigate 单一参数
public goToGoodsListPage(): void {
    // 第一种方式
    this._router.navigate([`/goodsList/${this.id}`]);
    // 第二种方式 与第一种方式达到相同的效果
    this._router.navigate(['/goodsList', this.id]);
  }
// html中调用这个方法,等同于使用a标签的routerLink属性
<button (click)="goToGoodsListPage()">切换到商品列表组件</button>

多个参数

  public goToPersonalCenterPage(): void {
    this._router.navigate(['/personalCenter'], {queryParams:{name: 'zs', age: 16}});
  }
  // html中调用
   <button (click)="goToPersonalCenterPage()">切换到个人中心组件</button>
  1. router.navigateByUrl
// 传的第一个参数是数组的形式,而navigate的第一个参数是数组的方式
// 他的传参目前是拼接在url上边的
  public goToPersonalCenterPage(): void {
    this._router.navigateByUrl(`/personalCenter?name=zs&age=16`);
  }

在路由中接收参数的2种方式

  1. 接收params类型的参数
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);
    });
  }
  1. 接收queryParams类型的参数
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);
    });
  }

响应式表单

提供对底层表单对象模型底层表单对象模型}底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮,它们的可扩展性、可复用性和可测试性都更高。而且控件更新的效率更高效率更高效率更高,因为FormControl 的实例总会返回一个新值,而不会更新现有的数据模型,如果表单是你的应用程序的关键部分,或者可扩展性很强,那就使用响应式表单

  1. 在模块文件中引入响应式表单模块
import { ReactiveFormsModule } from '@angular/forms';
  1. 在组件中引入表单组
import { FormGroup, FormControl } from '@angular/forms';
  1. 创建一个FormGroup实例,并把这个FormGroup模型关联到视图
 this.profileForm = new FormGroup({
      name: new FormControl(''),
      password: new FormControl(''),
   });
<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>

HTTP

Angular给应用提供了一个HTTP客户端 API,也就是 @angular/common/http中的 HttpClient服务类。

使用HttpClient

  1. 在根模块下导入HttpClient
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
// 导入HttpClientModule
import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
  ],
  exports: [],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  1. 在服务类中依赖注入 (需要在服务类中通过HttpClient去进行通讯)
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()

export class GoodsListService {
  constructor(private http: HttpClient) { }
}
  1. 使用HttpClient返回的都是可观察对象(observable)类型的服务。因此我们还需要在服务类中导入RxJS 可观察对象可观察对象和可能会使用到的操作符操作符。
import { Observable } from 'rxjs';
import { pluck } from 'rxjs/operators'; // 此操作符是用来获取某个字段内容

常用的请求方式

  1. 从服务器请求数据 HttpClient.get()
  // 在服务类中去封装和服务端通讯的方法
  
  public getHttpResult(code: string, name: string): Observable<any> {
    const url: string = '';  // 这是请求的地址
    return this._http.get(url, { params: { code, name } });
  }
  1. 发送数据到服务器 HttpClient.post()
  public postHttpResult(body: any): Observable<any> {
    const url: string = ''; // 这是请求的地址
    return this._http.post(url, body);
  }

错误处理

在调用接口的时候,当遇到接口请求失败或者报错的时候,前端需要做一些错误的提示信息展示,具体操作如下:

    this._goodsListService.getHttpResult('12', 'zs')
    .subscribe((res) => { // 由于httpClient返回的是observable,他必须被订阅之后才可以执行并返回结果
      console.log(res);
    }, (error) => { // 这里是接口报错的处理错误的地方
      console.log(error);
    });