Angular-官方文档学习-1

本文是Angular入门教程,详细介绍了如何配置环境、使用Angular CLI创建项目、安装依赖,包括Primeng、Font Awesome和动画库。讨论了Angular的轻逻辑原则,讲解了组件、模块、服务与依赖注入的概念,以及表单数据验证。同时,通过创建购物车组件展示了数据管理的实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Angular

简介

AngularJS 是一个 JavaScript 框架。它可通过

AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定数据到 HTML。

AngularJS 扩展了 HTML

AngularJS 通过 ng-directives 扩展了 HTML。

ng-app 指令定义一个 AngularJS 应用程序。

ng-model 指令把元素值(比如输入域的值)绑定到应用程序。

ng-bind 指令把应用程序数据绑定到 HTML 视图。

Angular提倡的文件命名方式

组件名称.component.ts

组件的HTML模板命名为: 组件名称.component.html

组件的样式文件命名为: 组件名称.component.css

在使用angular前,需要先配置环境

  1. node.js

  2. 安装完node后可以将npm资源库设置成国内淘宝镜像,下载cnpm

    npm config set registry https://registry.npm.taobao.org

    npm install -g cnpm --registry=https://registry.npm.taobao.org

  3. 安装CLI

    3.1:在安装了cnpm的目录下打开命令行

    image-20201230131356017

    3.2:输入cnpm install -g @angular/cli

    3.3:通过ng v命令可查看是否安装成功

    image-20201230131500650

  4. 安装TypeScript

    4.1:cnpm install -g typescript

    4.2:tsc -v可查看是否安装成功

  5. 安装saas

    5.1:npm install node-sass --registry=http://registry.npm.taobao.org

    5.2:安装saas中间会报几次错误,遇到错误重新安装即可

搭建项目

1.使用命令行创建
1.1cnpm下创建项目。(做Demo时候可以使用)

​ 切换到要创建项目的目录,命令行输入:ng new frontend

2.使用cnpm安装Primeng
2.1 进入项目根目录
2.2 cnpm install primeng --save

image-20201230132233434

2.3安装第三方字体awesome:

​ cnpm install font-awesome

2.4安装Augular4+动画

​ cnpm install @angular/animations --save

2.5安装jquery

​ npm install jquery --save(遇到错误重复安装即可)

​ npm install @types/jquery --save

2.6命令行输入ng serve即可通过localhost:4200访问欢迎界面

image-20201230132523751

image-20201230133626098
  • @Component:这是一个 Decorator(装饰器),其作用类似于 Java 里面的注解。Decorator 这个语言特性目前(2017-10)处于 Stage 2(草稿)状态,还不是 ECMA 的正式规范。
  • selector:组件的标签名,外部使用者可以这样来使用这个组件:。默认情况下,ng 命令生成出来的组件都会带上一个 app 前缀,如果你不喜欢,可以在 angular-cli.json 里面修改 prefix 配置项,设置为空字符串将会不带任何前缀。
  • templateUrl:引用外部的 HTML 模板。如果你想直接编写内联模板,可以使用 template,支持 ES6 引入的“模板字符串”写法
  • styleUrls:引用外部 CSS 样式文件,这是一个数组,也就意味着可以引用多份 CSS 文件。
  • export class AppComponent:这是 ES6 里面引入的模块和 class 定义方式
何为“轻逻辑”?

简而言之,所谓“轻逻辑”就是说,你不能在模板里面编写非常复杂的 JavaScript 表达式。比如,Angular 的模板语法就有规定:

  • 你不能在模板里面 new 对象
  • 不能使用=、+=、-=这类的表达式
  • 不能用++、–运算符
  • 不能使用位运算符

第一个组件

命令行窗口输入 ng generate component login --inline-template --inline-style

参数generate用来生成文件,参数component说明要生成一个组件,login是组件名称,后面的两个参数是告诉angular-cli:生成组件时,请把组件的HTML模板和CSS样式和组件放在同一个文件中(其实分开文件更清晰。)

可以把上面的命令改写成 ng g c login -it -is

angular-cli为我们在\src\app目录下生成了一个新文件夹login,在login目录下生成了2个文件

image-20201230143202257

@Component修饰配置中的 selector: 'app-login',意味着可以在其他组件的template中使用 <app-login></app-login> 来引用这个组件。

image-20201230143354829

什么是模块?

简单来说模块就是提供相对独立功能的功能块,每块聚焦于一个特定业务领域。Angular内建的很多库是以模块形式提供的,比如FormsModule封装了表单处理,HttpModule封装了Http的处理等等。每个Angular应用至少有一个模块类 —— 根模块,我们将通过引导根模块来启动应用。按照约定,根模块的类名叫做AppModule,被放在 app.module.ts 文件中。

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';


@NgModule({ //@NgModule装饰器用来为模块定义元数据。
  declarations: [
    AppComponent,
    LoginComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,


  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
Angular的服务与依赖注入

创建一个 AuthService , 在 src\app 下建立一个 core 的子文件夹( src/app/core ),命令行中输入 ng g s core/auth ( s这里是service的缩写,core/auth 是说在 core 的目录下建立 auth 服务相关文件

service 添加一个方法,为这个方法指定了返回类型和参数类型。这就是 TypeScript 的好处,有了类型约束,在别处调用这个方法时,如果给出的参数类型或返回类型不正确,IDE就可以直接告诉你错了。

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

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

  constructor() { }
  loginWithCredentials(username: string, password: string): boolean {
    if(username === 'wangpeng')
      return true;
    return false;
  }
}

这个service虽然被创建了,但仍无法在Component中使用,可以直接在Component中import这个服务,但这样耦合性比较高,Angular提供了依赖性注入的方法

如何使用DI

在组件的修饰器中配置AuthService,然后在组件的构造函数中使用参数进行依赖注入。

import { Component, Inject, OnInit } from '@angular/core';
import { AuthService } from '../core/auth.service';

@Component({
  selector: 'app-login',
  template: `
  <div>
      <input #usernameRef type="text">
      <input #passwordRef type="password">
      <button (click)="onClick(usernameRef.value, passwordRef.value)">Login</button>
    </div>
  `,
  styles: [
  ],
  providers:[AuthService]//在providers中配置AuthService
})
export class LoginComponent implements OnInit {
  //在构造函数中将AuthService示例注入到成员变量service中
  //而且我们不需要显式声明成员变量service了
  constructor(private service:AuthService) { }

  ngOnInit(): void {
  }
  onClick(username:string, password:string) {
    console.log('auth result is: ' + this.service.loginWithCredentials(username, password));
  }
}

双向数据绑定

angular 提供了一个双向数据绑定的机制。这个机制是这样的,在组件中提供成员数据变量,然后在模板中引用这个数据变量。

在class中声明变量:

  username = "";
  password = "";

方法改造,去掉onClick中的参数,改为this.*调用

onClick() {
    console.log('auth result is: ' + this.service.loginWithCredentials(this.username, this.password));
  }

模板:

    <div>
      <input type="text"
        [(ngModel)]="username"
        />
      <input type="password"
        [(ngModel)]="password"
        />
      <button (click)="onClick()">Login</button>
    </div>

[(ngModel)]="username"

[]的作用:把等号后面当成表达式来解析而不是当成字符串,如果去掉方括号等于将 ngModel 赋值成 username 这个字符串。方括号的含义是单向绑定,即在组件中给 model 赋的值会设置到 HTML 的 input 控件中。 [()] 是双向绑定的意思,即HTML对应控件的状态的改变会反射设置到组件的 model 中。

ngModel 是 FormModule 中提供的指令,负责从Domain Model(这里就是 username 或 password )中创建一个 FormControl 的实例,并将这个实例和表单的控件绑定起来。

表单数据的验证
<div>
      <input type="text"
        [(ngModel)]="username"
        #usernameRef="ngModel"
        required
        minlength="3"
        />
        {{ usernameRef.errors | json }}
        <div *ngIf="usernameRef.errors?.required">this is required</div>
        <div *ngIf="usernameRef.errors?.minlength">should be at least 3 charactors</div>
      <input required type="password"
        [(ngModel)]="password"
        #passwordRef="ngModel"
        />
        <div *ngIf="passwordRef.errors?.required">this is required</div>
      <button (click)="onClick()">Login</button>
    </div

ngIf是一个Angular2的指令,是用于做条件判断的。*ngIf="usernameRef.errors?.required"的意思是当usernameRef.errors.requiredtrue时显示div标签。那么那个?是干嘛的呢?因为errors可能是个null,如果这个时候调用errorsrequired属性肯定会引发异常,那么?就是标明errors可能为空,在其为空时就不用调用后面的属性了。

<div>
      <form #formRef="ngForm">
        <input type="text"
          name="username"//要指定name不然会报错
          [(ngModel)]="username"
          #usernameRef="ngModel"
          required
          minlength="3"
          />
          <div *ngIf="usernameRef.errors?.required">this is required</div>
          <div *ngIf="usernameRef.errors?.minlength">should be at least 3 charactors</div>
        <input type="password"
          name="password"
          [(ngModel)]="password"
          #passwordRef="ngModel"
          required
          />
          <div *ngIf="passwordRef.errors?.required">this is required</div>
        <button (click)="onClick()">Login</button>
        <button type="submit">Submit</button>
      </form>
    </div>

表单项过多时可以用HTML提供的fieldset标签来处理,<fieldset ngModelGroup="login"> 对于 fieldset 之内的数据都分组到了 login 对象中。

*ngFor 是一个 “结构型指令”。结构型指令会通过添加、删除和操纵它们的宿主元素等方式塑造或重塑 DOM 的结构。带有星号 * 的指令都是结构型指令。

Angular 模板语法的五个常用特性:

  • *ngFor
  • *ngIf
  • 插值 {{}}
  • 属性绑定 []
  • 事件绑定 ()

组件

组件在用户界面(也就是 UI)中定义了一些责任区,让你能复用这些 UI 功能集。你已经通过商品列表组件构建了一个。

组件包含三部分:

  • 一个组件类,它用来处理数据和功能。上一节,我们在组件类中定义了商品数据和 share() 方法,它们分别用来处理数据和功能。
  • 一个 HTML 模板,它决定了 UI。在上一节中,商品列表的 HTML 模板用来显示每个商品的名称、描述和 “Share” 按钮。
  • 组件专属的样式定义了外观和感觉。商品列表中还没有定义任何样式,那属于组件 CSS 负责。

image-20201230172333012

  • app-root(橙色框)是应用的外壳。这是要加载的第一个组件,也是所有其它组件的父组件。你可以把它想象成一个基础页面。
  • app-top-bar(蓝色背景)是商店名称和结帐按钮。
  • app-product-list(紫色框)是你在上一节中修改过的商品列表。

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

定义一个带 @Input() 装饰器的 product 属性。@Input() 装饰器指出其属性值是从该组件的父组件商品列表组件中传入的。

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

@Output() 装饰器,事件发射器 EventEmitter()

@Output() notify = new EventEmitter();notify 属性发生变化时发出事件。

父组件要接收子组件发出的事件

路由

Angular 路由器能让你在不同的视图中显示产品的详情,每个产品都有自己的 URL。当用户执行应用任务时,路由器可以从一个视图导航到另一个视图(但在同一个页面)。比如:

  • 在地址栏中输入一个 URL,导航到相应的页面。
  • 点击页面上的链接,导航到新页面。
  • 点击浏览器的后退和前进按钮,在浏览器的历史中前后导航
  1. 为商品详情生成一个新组件。把组件命名为 product-details

    提示:在文件列表框中,右键单击 app 文件夹,选择 Angular GeneratorComponent

  2. app.module.ts 中,添加一个商品详情路由,该路由的 pathproducts/:productIdcomponentProductDetailsComponent

    路由会将一个或多个 URL 路径与一个组件关联起来。

    image-20201231101016242

  3. 该指令配置组件的模板,以定义用户如何导航到路由或 URL。当用户点击商品名称时,应用就会显示那个商品的详情。

    1. 打开 product-list.component.html

    2. 修改 *ngFor 指令,在遍历列表的过程中把 products 数组中的每个索引赋值给 productId 变量。

    3. 修改商品名称的链接,使其包含 routerLink

  4. RouterLink 指令让路由器控制了一个链接元素。在这种情况下,路由或 URL 包含一个固定的区段( /products ),但其最后一个区段是变量,要插入当前商品的 id 属性。例如,id 为 1 的商品的 URL 类似于 https://getting-started-myfork.stackblitz.io/products/1

使用路由信息

  1. 打开 product-details.component.ts 文件

  2. 改用外部文件中的商品数据。

    1. @angular/router 包导入 ActivatedRoute,从 ../products 文件导入 products 数组。

      image-20201231103056404

    2. 定义 product 属性,并将 ActivatedRoute 作为参数添加到构造函数的括号中,以便把它注入到构造函数中。

      image-20201231103132849

      (ActivatedRoute 专门用于由 Angular 路由器加载的每个路由组件。它包含关于该路由,路由参数以及与该路由关联的其它数据的信息。)

  3. ngOnInit() 方法中订阅了路由参数,并且根据 productId 获取了该产品。

  4. 修改模板,在 *ngIf 中显示商品详情。

    image-20201231103210010

    currency 管道来把 product.price 从数字转换成货币字符串。管道给了你一种在 HTML 模板中转换数据的方式。

管理数据

  • 修改商品详情视图,让它包含一个 “Buy” 按钮,它会把当前商品添加到由 “购物车服务” 管理的商品列表中。
  • 添加一个购物车组件,它会显示购物车中的商品。
  • 添加一个配送组件,它会使用 Angular 的 HttpClient.json 文件中检索配送数据来取得购物车中这些商品的运费。
创建购物车服务

生成service文件,并在其中写入有关商品与购物车操作的函数,引入HttpClient包,注入构造函数中。

image-20201231105111019

product-details.component.ts 中导入购物车服务,并在构造函数的参数中注入服务

image-20201231105322612

添加购物车组件,在app.module.ts中添加路由:{ path: 'cart', component: CartComponent },

显示购物车商品

在购物车组件中注入购物车服务,将购物车服务中定义的方法写入

image-20201231105638073

检索运费价格

服务器通常采用流的形式返回数据。 流是很有用的,因为它们可以很容易地转换返回的数据,也可以修改你请求数据的方式。 Angular 的 HTTP 客户端( HttpClient )是一种内置的方式,可以从外部 API 中获取数据,并以流的形式提供给你的应用。

要使用Angular的HTTP客户端,必须在app.module.ts中导入HttpClientModule

import { HttpClientModule } from '@angular/common/http';
@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,//要import进来
    ReactiveFormsModule,
    ...省略
  ],
新建组件Shipping来使用CartService

image-20201231110117411

利用 async 管道修改配送组件的模板,以显示配送类型和价格;

async 管道从数据流中返回最新值,并在所属组件的生命期内持续返回。当 Angular 销毁该组件时,async 管道会自动停止。

<h3>Shipping Prices</h3>

<div class="shipping-item" *ngFor="let shipping of shippingCosts | async">
  <span>{{ shipping.type }}</span>
  <span>{{ shipping.price | currency }}</span>
</div>
在购物车视图中添加一个到配送视图的链接
<p>
  <a routerLink="/shipping">Shipping Prices</a>
</p>

Angular中的表单

Angular 中的表单建立在标准 HTML 表单功能之上,以帮助你创建自定义表单控件和轻松的验证体验。Angular 响应式表单有两个部分:组件中那些用于存储和管理表单的对象,以及表单在模板中的可视化

ReactiveFormsModule 中提供了 FormBuilder 服务,FormBuilder 服务为生成控件提供了方便的方法。需要导入并注入该服务,然后才能使用它。

image-20201231112335889

  1. 在CartComponent类中,定义checkoutForm来存储表单模型

  2. checkoutForm 属性设置为一个包含 nameaddress 字段的表单模型。使用 FormBuildergroup() 方法来创建它,把该语句加入构造函数的花括号 {} 中间。

  3. 创建结账表单

    1. 使用 formGroup 属性绑定把 checkoutForm 绑定到模板中的 form 标签上

    2. form 标签上,使用 ngSubmit 事件绑定来监听表单提交,并使用 checkoutForm 值调用 onSubmit() 方法

    3. nameaddress 添加输入字段。使用 formControlName 属性绑定来把 checkoutForm 表单控件中的 nameaddress 绑定到它们的输入字段

      <form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)">
        <div>
          <label for="name">
            Name
          </label>
          <input id="name" type="text" formControlName="name">
        </div>
        <div>
          <label for="address">
            Address
          </label>
          <input id="address" type="text" formControlName="address">
        </div>
        <button class="button" type="submit">Purchase</button>
      </form>
      
  4. 最终效果:

image-20201231112817811

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值