ANGULAR框架

1.设置开发环境

安装Node.js和npm,全局安装Angular CLI

npm install -g @angular/cli

 2.创建新项目

打开终端窗口,使用 ng add 命令往新项目中添加一些预先打包好的功能, Angular Material 就为一些典型布局提供了图纸

ng new my-app

3.启动开发服务器

监听文件变化,并在修改这些文件时重新构建此应用,在4200端口,http://localhost:4200/.

cd my-app
ng serve --open

4.编辑Angular组件

app-root 的根组件。 你可以在 ./src/app/app.component.ts 目录下找到它。

把 title 属性从 'app' 改为 'My First Angular App!'

export class AppComponent {
  title = 'My First Angular App!';
}

设计css,打开 src/app/app.component.css 并给这个组件设置一些样式

h1 {
  color: #369;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 250%;
}

Angular CLI 的工作原理

src文件夹

src文件夹: Angular 组件、模板、样式、图片以及你的应用所需的任何东西

app/app.component.{ts,html,css,spec.ts}

使用 HTML 模板、CSS 样式和单元测试定义 AppComponent 组件。 它是组件,随着应用的成长它会成为一棵组件树的根节点。

app/app.module.ts

定义 AppModule根模块为 Angular 描述如何组装应用。 目前,它只声明了 AppComponent。 不久,它将声明更多组件。

assets/*

这个文件夹下你可以放图片等任何东西,在构建应用时,它们全都会拷贝到发布包中。

environments/*

这个文件夹中包括为各个目标环境准备的文件,它们导出了一些应用中要用到的配置变量。 这些文件会在构建应用时被替换。 比如你可能在生产环境中使用不同的 API 端点地址,或使用不同的统计 Token 参数。 甚至使用一些模拟服务。 所有这些,CLI 都替你考虑到了。

browserslist

一个配置文件,用来在不同的前端工具之间共享目标浏览器

favicon.ico

每个网站都希望自己在书签栏中能好看一点。 请把它换成你自己的图标。

index.html

这是别人访问你的网站是看到的主页面的 HTML 文件。 大多数情况下你都不用编辑它。 在构建应用时,CLI 会自动把所有 js 和 css 文件添加进去,所以你不必在这里手动添加任何 <script> 或 <link> 标签。

karma.conf.js

Karma的单元测试配置,当运行 ng test 时会用到它。

main.ts

这是应用的主要入口点。 使用JIT 编译器编译本应用,并启动应用的根模块 AppModule,使其运行在浏览器中。 你还可以使用AOT 编译器,而不用修改任何代码 —— 只要给 ng build 或 ng serve 传入 --aot 参数就可以了。

polyfills.ts

不同的浏览器对 Web 标准的支持程度也不同。 腻子脚本(polyfill)能把这些不同点进行标准化。 你只要使用 core-js 和 zone.js 通常就够了,不过你也可以查看浏览器支持指南以了解更多信息。

styles.css

这里是你的全局样式。 大多数情况下,你会希望在组件中使用局部样式,以利于维护,不过那些会影响你整个应用的样式你还是需要集中存放在这里。

test.ts

这是单元测试的主要入口点。 它有一些你不熟悉的自定义配置,不过你并不需要编辑这里的任何东西。

tsconfig.{app|spec}.json

TypeScript 编译器的配置文件。tsconfig.app.json 是为 Angular 应用准备的,而 tsconfig.spec.json 是为单元测试准备的。

tslint.json

额外的 Linting 配置。当运行 ng lint 时,它会供带有 Codelyzer 的 TSLint 使用。 Linting 可以帮你们保持代码风格的一致性。

 根目录

和src/平级

文件

用途

e2e/

在 e2e/ 下是端到端(end-to-end)测试。 它们不在 src/下,是因为端到端测试实际上和应用是相互独立的,它只适用于测试你的应用而已。 这也就是为什么它会拥有自己的 tsconfig.json

node_modules/

Node.js 创建了这个文件夹,并且把 package.json 中列举的所有第三方模块都放在其中。

.editorconfig

给你的编辑器看的一个简单配置文件,它用来确保参与你项目的每个人都具有基本的编辑器配置。 大多数的编辑器都支持 .editorconfig 文件,详情参见 http://editorconfig.org 。

.gitignore

一个 Git 的配置文件,用来确保某些自动生成的文件不会被提交到源码控制系统中。

angular.json

Angular CLI 的配置文件。 在这个文件中,你可以设置一系列默认值,还可以配置项目编译时要包含的那些文件。 要了解更多,请参阅它的官方文档。

package.json

npm 配置文件,其中列出了项目使用到的第三方依赖包。 你还可以在这里添加自己的自定义脚本

protractor.conf.js

Protractor使用的端到端测试配置文件,当运行 ng e2e 的时候会用到它。

README.md

项目的基础文档,预先写入了 CLI 命令的信息。 别忘了用项目文档改进它,以便每个查看此仓库的人都能据此构建出你的应用。

tsconfig.json

TypeScript 编译器的配置,你的 IDE 会借助它来给你提供更好的帮助。

tslint.json

TSLintCodelyzer用的配置信息,当运行 ng lint 时会用到。 Lint 功能可以帮你保持代码风格的统一。

组件是 Angular 应用中的基本构造块 ,AppComponent三个实现文件:

  • app.component.ts— 组件的类代码,这是用 TypeScript 写的。

  • app.component.html— 组件的模板,这是用 HTML 写的。

  • app.component.css— 组件的私有 CSS 样式。

修改应用标题

title = 'My First Project';/*在app.component.ts*/
<h1>{{title}}</h1>/*在src/app/app.component.html,双花括号是插值绑定语法*/

添加应用样式

    /* Application-wide Styles */
    h1 {
      color: #369;
      font-family: Arial, Helvetica, sans-serif;
      font-size: 250%;
    }
    h2, h3 {
      color: #444;
      font-family: Arial, Helvetica, sans-serif;
      font-weight: lighter;
    }
    body {
      margin: 2em;
    }
    body, input[text], button {
      color: #888;
      font-family: Cambria, Georgia;
    }
    /* everywhere else */
    * {
      font-family: Arial, Helvetica, sans-serif;
    }

src/app/app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Tour of Heroes';
}
import { Component, OnInit } from '@angular/core';
/*导入 Component 符号,并为组件类加上 @Component 装饰器*/
@Component({
  selector: 'app-heroes',//组件的选择器(CSS 元素选择器)
  templateUrl: './heroes.component.html',//组件模板文件的位置
  styleUrls: ['./heroes.component.css']//组件私有 CSS 样式表文件的位置
})
export class HeroesComponent implements OnInit {

  constructor() { }

  ngOnInit() {// a lifecycle hook ,创建完组件后很快就会调用 ngOnInit,放置初始化逻辑的地方
  }

}

添加 hero 属性

hero = 'Windstorm';//heroes.component.ts中添加一个 hero 属性
{{hero}}// heroes.component.html

显示 HeroesComponent 视图

HeroesComponent 加到AppComponent 的模板

src/app/app.component.html

      

<h1>{{title}}</h1>
<app-heroes></app-heroes>
src/app/hero.ts

export class Hero {
  id: number;
  name: string;//添加 id 和 name 属性
}


src/app/heroes/heroes.component.ts


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

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
  hero: Hero = {
    id: 1,
    name: 'Windstorm'
  };

  constructor() { }

  ngOnInit() {
  }

}

显示 hero 对象

heroes.component.html

<h2>{{ hero.name }} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div><span>name: </span>{{hero.name}}</div>

使用 UppercasePipe 进行格式化

<h2>{{ hero.name | uppercase }} Details</h2>//显示成了大写字母

pipe operator ( | )

pipe是格式化字符串、金额、日期和其它显示数据的好办法

数据流从组件类流出到屏幕,并且从屏幕流回到组件类

**数据流动自动化,双向数据绑定:[(ngModel)] 是 Angular 的双向数据绑定语法,记得添加此模块FormsModule

<div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name">
    </label>
</div>

元数据(metadata)、顶级类 AppModule

@Component 装饰器和@NgModule 装饰器

app.module.ts (FormsModule symbol import)

 //从 @angular/forms 库中导入 FormsModule 符号    

import { FormsModule } from '@angular/forms'; // <-- NgModel lives here


//把 FormsModule 添加到 @NgModule 元数据的 imports 数组中,这里是该应用所需外部模块的列表

app.module.ts ( @NgModule imports)
imports: [
  BrowserModule,
  FormsModule
],

声明 HeroesComponent

每个组件都必须声明在(且只能声明在)一个 NgModule 中。

创建模拟(mock)的数据

src/app/ 文件夹中创建一个名叫 mock-heroes.ts 的文件

src/app/mock-heroes.ts


import { Hero } from './hero';

export const HEROES: Hero[] = [
  { id: 11, name: 'Mr. Nice' },
  { id: 12, name: 'Narco' },
  { id: 13, name: 'Bombasto' },
  { id: 14, name: 'Celeritas' },
  { id: 15, name: 'Magneta' },
  { id: 16, name: 'RubberMan' },
  { id: 17, name: 'Dynama' },
  { id: 18, name: 'Dr IQ' },
  { id: 19, name: 'Magma' },
  { id: 20, name: 'Tornado' }
];

显示数据

src/app/heroes/heroes.component.ts (import HEROES)

      

import { HEROES } from '../mock-heroes';

heroes = HEROES;

使用 *ngFor 列出

heroes.component.html (heroes template)

      

<h2>My Heroes</h2>
<ul class="heroes">
  <li *ngFor="let hero of heroes">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>
<!--*ngFor 是一个 Angular 的复写器(repeater)指令。 它会为列表中的每项数据复写它的宿主元素。heroes 就是来自 HeroesComponent 类的列表-->

@Component.styles、@Component.styleUrls 所指出的样式表文件中

src/app/heroes/heroes.component.ts (@Component)

      

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
/*
@Component 元数据中指定的样式和样式表都是局限于该组件的。

heroes.component.css 中的样式只会作用于 HeroesComponent,
既不会影响到组件外的 HTML,也不会影响到其它组件中的 HTML。
*/

主从结构

监听点击事件,添加 click 事件绑定

heroes.component.html (template excerpt)

      

<li *ngFor="let hero of heroes" (click)="onSelect(hero)">

添加 click 事件处理器

src/app/heroes/heroes.component.ts (onSelect)

      

selectedHero: Hero;

onSelect(hero: Hero): void {
  this.selectedHero = hero;
}

修改详情模板

hero 改名为 selectedHero

heroes.component.html (selected hero details)

      

<h2>{{ selectedHero.name | uppercase }} Details</h2>
<div><span>id: </span>{{selectedHero.id}}</div>
<div>
  <label>name:
    <input [(ngModel)]="selectedHero.name" placeholder="name">
  </label>
</div>

使用 *ngIf 隐藏空白的详情

把显示数据详情的 HTML 包裹在一个 <div> 中。 并且为这个 div 添加 Angular 的 *ngIf 指令,把它的值设置为 selectedHero

src/app/heroes/heroes.component.html (*ngIf)

      

<div *ngIf="selectedHero">

  <h2>{{ selectedHero.name | uppercase }} Details</h2>
  <div><span>id: </span>{{selectedHero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="selectedHero.name" placeholder="name">
    </label>
  </div>

</div>

CSS 类绑定机制

[class.some-css-class]="some-condition" 添加到你要施加样式的元素

heroes.component.html (toggle the 'selected' CSS class)

/*如果当前行的英雄和 selectedHero 相同,Angular 就会添加 CSS 类 selected,否则就会移除它*/      
<li *ngFor="let hero of heroes"
  [class.selected]="hero === selectedHero"
  (click)="onSelect(hero)">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

主从组件

把大型组件拆分成小一点的子组件

ng generate component hero-detail
src/app/hero-detail/hero-detail.component.html

      

<div *ngIf="hero">

  <h2>{{ hero.name | uppercase }} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>

</div>

添加 @Input() hero 属性

@Input是用来定义模块的输入的,用来让父模块往子模块传递内容,父模块在引用子模块的时候是用的[]

src/app/hero-detail/hero-detail.component.ts (import Hero)

      

import { Hero } from '../hero';

<app-hero-detail [hero]="selectedHero"></app-hero-detail>


//修改 @angular/core 的导入语句,导入 Input 符号

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

添加一个带有 @Input() 装饰器的 hero 属性。

@Input() hero: Hero;


heroes.component.html (HeroDetail binding)
<!-- HeroesComponent.selectedHero 绑定到该元素的 hero 属性-->
<app-hero-detail [hero]="selectedHero"></app-hero-detail>

单向数据绑定

<h2>My Heroes</h2>

<ul class="heroes">
  <li *ngFor="let hero of heroes"
    [class.selected]="hero === selectedHero"
    (click)="onSelect(hero)">
    <span class="badge">{{hero.id}}</span> {{hero.name}}
  </li>
</ul>

<app-hero-detail [hero]="selectedHero"></app-hero-detail>

创建服务

Angular 的依赖注入机制把它注入到 HeroesComponent 的构造函数中

将创建一个 MessageService,并且把它注入到两个地方:

  1. HeroService 中,它会使用该服务发送消息。

  2. MessagesComponent 中,它会显示其中的消息。

使用 Angular CLI 创建一个名叫 hero 的服务。

ng generate service hero
src/app/hero.service.ts (new service)

      

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

@Injectable({//@Injectable()装饰器,依赖注入系统的参与者
  providedIn: 'root',
})
export class HeroService {//提供一个可注入的服务

  constructor() { }

}

HeroService 可以从任何地方获取数据:Web 服务、本地存储(LocalStorage)或一个模拟的数据源。

import { Hero } from './hero';
import { HEROES } from './mock-heroes';
getHeroes(): Hero[] {//让它返回模拟列表
  return HEROES;
}

在将Service注入到Component之前,需要将service提供给依赖注入系统。

 通过 注册provider,创建和交付(deliver)service

用注册器(injector)注册它,injector是一个对象

默认情况下,Angular CLI 命令 ng generate service 会通过给 @Injectable 装饰器添加元数据的形式,

为该服务把提供商注册到根注入器上。可在不同层次上注册provider

自动在module层上提供服务

ng generate service hero --module=app
src/app/hero.service.ts

import { Injectable } from '@angular/core';
     
    import { Observable, of } from 'rxjs';
     
    import { Hero } from './hero';
    import { HEROES } from './mock-heroes';
    import { MessageService } from './message.service';
     
    @Injectable({
      providedIn: 'root',
    })
    export class HeroService {
     
      constructor(private messageService: MessageService) { }
/*1. 声明了一个私有 Service 属性
2. 把它标记为一个Service 的注入点。
设置成单例对象*/

     
      getHeroes(): Observable<Hero[]> {//获取数据
        // TODO: send the message _after_ fetching the heroes
        this.messageService.add('HeroService: fetched heroes');
        return of(HEROES);
      }
    }


src/app/message.service.ts
    import { Injectable } from '@angular/core';
     
    @Injectable({
      providedIn: 'root',
    })
    export class MessageService {
      messages: string[] = [];
     
      add(message: string) {//添加一条消息
        this.messages.push(message);
      }
     
      clear() {//清空缓存
        this.messages = [];
      }
    }

在component中调用

ngOnInit() {
  this.getHeroes();
}
  • 将数据访问逻辑重构到Service 类中
  • 根注入器中把Service 注册为该服务的提供商,以便在别处可以注入它
  • 使用Angular依赖注入机制注入组件
  • Service 中获取数据的方法提供了一个异步的函数签名

HeroService.getHeroes() 必须具有某种形式的异步函数签名HeroService.getHeroes() 将会HttpClient.get() 返回 Observable,

  • Observable 以及 RxJS 库
src/app/hero.service.ts (Observable imports)

import { Observable, of } from 'rxjs';
  • 使用 RxJS 的 of() 方法返回了一个模拟英雄数据的可观察对象 (Observable<Hero[]>)
getHeroes(): void {
  this.heroService.getHeroes()
      .subscribe(heroes => this.heroes = heroes);
}

Observable.subscribe() 是关键的差异点。 subscribe()函数这个英雄数组传给这个回调函数,该函数把英雄数组赋值给组件的 heroes 属性。

使用这种异步方式,当 HeroService 从远端服务器获取英雄数据时,就可以工作了。

HeroService显示消息:打开MessagesComponent 可以显示所有消息,导入MessageService,在constructor中注入

  • *ngIf 只有当在有消息时才会显示消息区。

  • *ngFor 用来在一系列 <div> 元素中展示消息列表。

  • Angular 的事件绑定把按钮的 click 事件绑定到了 MessageService.clear()

  • 在组件的 ngOnInit 生命周期钩子中调用 HeroService 方法,而不是构造函数中
  • 你创建了一个 MessageService,以便在类之间实现松耦合通讯
  • HeroService 连同注入到它的服务 MessageService 一起,注入到了组件中

猜你喜欢

转载自blog.csdn.net/xuxuan1997/article/details/81212712