Angular2详解

张子墨
2023-12-01

软件开发综合实训是Angular 2+的开发,通过一个实战项目复习一下Angular的使用和TypeScript的语法。

一、搭建脚手架

https://cli.angular.io/或者angular官网
1.1 安装Angular的CLI

npm install -g @angular/cli

1.2 创建一个新项目

ng new my-app

1.3 启动服务

cd my-app
ng serve –open

二、文件梳理

文件作用
app/app.component.{ts,html,css,spec.ts}appcomponent一起定义了模板的HTML、CSS样式表和单元测试。它的根的树变成一个嵌套的组件应用程序的发展。
app/app.module.tsappmodule定义,根模块的角度,讲述了如何装配的应用。现在就只有appcomponent。很快就会宣布更多的部件。
assets/*一个文件夹,然后将图像和其他拷贝当您构建应用
environments/*该文件夹包含一个文件的每个目的地的环境中,每个出口使用简单配置变量以在应用程序中。该文件被替换时你编写的。你可能使用不同的API端点来发展用于生产比你做不同的分析或表征。你甚至会使用一些模拟服务。不管怎样,CLI都能满足您的需求。
browserslist配置文件发送至目标浏览器之间共享不同的前端工具。
favicon.ico每个网站需要美观的书签栏。开始使用你自己的Angular图标。
index.html主HTML页面,当有人访问您的网站。大多数时候,你就不会对它进行编辑。自动添加所有的CLIjs和css当你建立了文件程序,所以,你永远不需要添加任何<script><link>在此手动标记。
karma.conf.js测试单元的配置业力的测试运行器在运行中,ng test。
main.ts主入口点。编制与应用JIT编译器和引导该应用程序的根模块(AppModule)在浏览器中运行。还可以使用AOT编译器而不用改变任何代码在评估报告–aot授旗ng build和ng serve命令。
polyfills.ts不同的浏览器有不同等级的支持的网络标准。polyfills帮助那些差异进行归一化。你应该很安全的core-js和zone.js但是,当然不能浏览器支持引导欲了解更多信息。
styles.css你去这里全局样式。大多数时候,你需要在你的本地组件样式,更便于维护,但风格影响所有你的应用程序需要在一个中心位置。
test.ts这是主入口点的单元测试。它具有一些自定义配置可能不熟悉,但它不需要编辑。
tsconfig.{appspec}.json
tslint.json额外Linting配置在ng lint运行中为TSLint合并到Codelyzer,Linting有助于让你的代码风格一致。

三、TypeScript

TypeScript官方网站

安装npm install -g typescript
编译tsc helloworld.ts

JavaScript和TypeScript对比

语言类型说明
JavaScriptmyVar = “String”;myVar = 28语法正常,变量改变为数字28
TypeScriptmyVar = “String”;myVar = 28TS明确类型,不允许

3.1 TypeScript类型声明:

myVar:string = “hello”;
myVar:Boolean = true;
myVar:any //可以是任何类型

3.2 TypeScript类

Class Car{
class Car{
	wheel:number = 4;
	drive{
	console.log('前端老司机要开车了')
	}
}


myCar:car = new Car()

3.3 TypeScript构造函数

class Car{
	speed:number;
	constructor(mph:number){
		this.speed = mph;
	}
}

myCar:car = new Car(70)//新建车对象传值,70传递给mph,mph赋值给speed

3.4 可见度
修饰面向对象中属性被访问的限制
(1)public
公开的。属性可以公开被访问,当前类、与当前类有关的外部,当前类的子类对象可访问
(2)protected
受保护的。当前类对象以及子类对象访问属性
(3)private
私有的。只有当前类对象才能访问属性

3.5 TypeScript箭头函数
lambda表达式
(1)()=>相当于function()
(2)()=>{something}

四、组件

切换到根目录,创建navbar、home、diretory组件

cd my-app
cd src/app
ng generate component navbar
ng generate home
ng generate diretory

创建好组建后,打开app.component.ts文件

当前组件@Component是来自@angular/core模块的对应一个方法,初始化已经创建好的
app.component.ts

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

@Component({
  //html中调用了这个选择器
  selector: 'app-root',
  //当选择器被执行时,就会执行template
  templateUrl: './app.component.html',
  //当template执行后,就会执行style.css
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Welcome to 极客园地!';
  name = "Hello World!";
}

app.component.html

<h1>
	{{tittle}}
</h1>

app.component.css

h1{
	color: red;
}

p{
	color: blue;
}

五、数据绑定

三步骤:
I.找到要绑定数据组件的html
II.准备当前数据
III.在html中调用数据

模板绑定只能使用字符串,属性绑定可以使用字符串表达式,前者更常用

5.1 属性绑定property binding
[something]=’表达式’

5.2 双向数据绑定:MVVM设计模式中显著地特征,简单来说就是当页面发生变化,数据发生变化 || 数据发生变化,页面就发生变化,通过[(ngModel)]来实现数据的双向绑定
形式:[(ngModel)]=”model”

app.component.html

<h1>
	{{tittle}}
</h1>

<p>
	{{name}}
</p>	


<app-home></app-home>

home.component.ts

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

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css'],
})
export class HomeComponent implements OnInit {
  
  //准备数据
  homeTitle = "homeTitle";

  myString = "I like coding!";

  person = {
    name:”geekfanr”,
    color:black;
  }

  constructor() {
    
  }
  
  ngOnInit() {
  }

}

home.component.html

<p>
  home works!
</p>  

<!-- 使用数据{{ 属性 }} -->

<p>
  {{homeTitle}}
<p>

<input value={{myString}}><!-- 模板绑定 -->
<input [value]="myString">

<input [(ngModel)]="person.name">
<input [(ngModel)]="person.color">

<p>{{person.name}</p>
<p>{{person.color}</p>

六、@Input及事件绑定

6.1 @Input:用来让父模块往子模块传递内容所使用的特殊模块
场景展示:父级组件像子级组件传递数据
app.component.ts->home.component.html

6.2 自定义属性:自己定义的属性(非系统内置属性),常用于多组件传值配合@input使用

例如:[person]=”person”

6.3 事件绑定:将某种事件(点击,鼠标,键盘)绑定到指定的元素上,时间的表示有两种,分别是on-event || (event)

6.4 事件绑定步骤:
①设定元素并制定事件(home.component.html

②实现事件(home.component.ts

③实现传值(形参实参)(clickHere(‘I like coding!’)

app.component.ts

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

@Component({
  //html中调用了这个选择器
  selector: 'app-root',
  //当选择器被执行时,就会执行template
  templateUrl: './app.component.html',
  //当template执行后,就会执行style.css
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Welcome to 极客园地!';
  name = "Hello World!";

  person = {
    name:"geekfanr",
    color:black;
  };
}

`app.component.html`
<h1>
	{{tittle}}
</h1>


<!-- 两个组件公用的接口 -->
<app-home [person] = "person"></app-home>

`home.component.ts`
import {Component, OnInit, Input} from '@angular/core';

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

  @Input() person;

//TS中不需要function关键字
  clickHere(val){
    alert(val);
  }

  constructor() {
    
  }
  
  ngOnInit() {
  }

}

home.component.html

<p>home works!</p>  

<p>{{person.name}}</p>

<p>{{person.color}}</p>

<!-- button on-click="clickHere()">Click Here</button -->
<button (click)="clickHere('I like coding!')">Click Here</button>

七、@Output模块

7.1 当子模块想自定义一些event传递给父模块时,我们需要使用到@output

7.2 场景:自己组建传递时间给父级组件触发

home.component.html—>>>app.component.ts[alert(‘I am yelling’);]
        (EventEmitter)

7.3 自定义事件:自己定义的事件(非系统内置事件),常用于子组件传递事件到父组件且配合@Output使用
(onYell) = “yell()”

7.4 操作步骤:

①公共接口 app.html
②实现方法 app.ts
③引入Output模块home.ts
④创建自定义事件home.ts
⑤触发事件方法home.ts

home.component.html

<p>home works!</p>  

<p>{{person.name}}</p>

<p>{{person.color}}</p>

<!-- button on-click="clickHere()">Click Here</button -->
<button (click)="clickHere('I like coding!')">Click Here</button>

<hr>

<ng-content></ng-content>

<hr>

<button (click)="fireYellEvent()">Hit me</button>

home.comp[onent.ts

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

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

  @Input() person;

  @Output() onYell = new EventEmitter();

  clickHere(val){
    alert(val);
  }

//fireYellEvent方法触发app.component.ts中的yell方法,this指代HomeComponent组件
  fireYellEvent(){
    this.onYell.emit();
  }

  constructor() {
    
  }
  
  ngOnInit() {
  }

}

`app.component.html`
<h1>
	{{tittle}}
</h1>


<!-- 两个组件公用的接口 -->
<app-home [person] = "person" (onYell) = "yell()">
Yell
</app-home>

app.component.ts

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

@Component({
  //html中调用了这个选择器
  selector: 'app-root',
  //当选择器被执行时,就会执行template
  templateUrl: './app.component.html',
  //当template执行后,就会执行style.css
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Welcome to 极客园地!';
  name = "Hello World!";

  person = {
    name:"geekfanr",
    color:black;
  };

//yell方法触发app.conponent.html中的onYell方法
  yell(){
    alert('I amm Yelling!');
  }
}

八、路由

8.1 定义:从一个页面链接到另一个页面,页面之间的跳转就需要通过路由表实现

8.2 场景展示:点击不同的按钮,跳转到不同的页面

8.3 路由流程:

①引入路由模块
import{Routes} from @angular/router
②配置路由

   网页路径
{path:’dir’,component:DComponent}
{path:’’,component:HomeComponent}
      执行组件

③路由输出配置
<router-outlet></router-outlet>
④路由链接
<a [routerLink]=”[‘home’]”>首页</a>
app.component.html

<h1>
	{{tittle}}
</h1>


<router-outlet></router-outlet>

app.routes.ts

//路由
import {Routes, RouterModule} from "@angular/router";
import {DirectoryComponent} from "./directory/directory.component";
import {HomeComponent} from "./home/home.component";
import {ModuleWithProviders} from "@angular/core";
const appRoutes:Routes=[
  {
    //路由参数
    //path:"directory/:person",component:DirectoryComponent
    path:"directory",component:DirectoryComponent
  },
  {
    path:"",component:HomeComponent
  }
];
export const routing:ModuleWithProviders=RouterModule.forRoot(appRoutes);

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { NavCo mponent } from './nav/nav.component';
import { DirectoryComponent } from './directory/directory.component';

import { routing } from ',/app.routes';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    NavComponent,
    DirectoryComponent,
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    routing,
    AngularFireModule.initializeApp(environment.firebase, 'app-directory')
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

`directory.component.ts`
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-directory',
  templateUrl: './directory.component.html',
  styleUrls: ['./directory.component.css'],
})
export class DirectoryComponent implements OnInit {
  constructer(){}

  ngOnInit() {
    
  }
}

九、路由参数

9.1 路由链接<a [routerLink]=”[‘home’]”>首页</a>

9.2 路由参数:页面与页面之间数据的一种传递方式

场景展示:
从商品展示页面传递参数到商品详细页面

参数表示:path:”directory/:person”

app.routes.ts

//路由
import {Routes, RouterModule} from "@angular/router";
import {DirectoryComponent} from "./directory/directory.component";
import {HomeComponent} from "./home/home.component";
import {ModuleWithProviders} from "@angular/core";
const appRoutes:Routes=[
  {
    //路由参数
    //path:"directory/:person",component:DirectoryComponent
    path:'directory/:person',component:DirectoryComponent
  },
  {
    path:'',component:HomeComponent
  }
];
export const routing:ModuleWithProviders=RouterModule.forRoot(appRoutes);

app.component.html

<nav>
	<!--使用a标签同样可以实现跳转,但每次请求都会刷新,影响性能
	<li><a href="/">Home</a></li>
	<li><a href="/directory">Directory</a></li>
	-->
	<li><a [routerLink]="['/']">Home</a></li>
	<li><a [routerLink]="['directory']">Directory</a></li>
</nav>

<router-outlet></router-outlet>

directory.component.ts

import { Component, OnInit } from '@angular/core';
//引入路由模块
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-directory',
  templateUrl: './directory.component.html',
  styleUrls: ['./directory.component.css'],
})
export class DirectoryComponent implements OnInit {
  //外部定义person属性
  person:string;
  //当组件被激活,直接调用
  constructer(private route:ActivatedRoute) {
  	this.person = route.snapshot.params['person'];
  }

  ngOnInit() {
    
  }
}

directory.component.html

<p>
  directory works
</p>

<p>{{person}}</p>

十、指令

指令定义:具备某种能力去完成某种任务,在ng2中有三种类型的指令,分别是:

  • 组件
  • 属性指令
  • 结构指令

10.1 组件指令
例如:<app-home> || <router-outlet>调用home模板、样式;在无网络刷新情况下进行路由

10.2 属性指令
改变当前DOM元素结构样式/属性,并不改变结构
例如:ngClass=”类名”

10.3 结构指令
改变当前DOM元素结构
例如:*nglf=”表达式”
directory.component.html

<p [ngClass]="classes">
  directory works
</p>

<!-- *ngFor -->
<ul>
	<li *ngFor="let person of people">{{person.name}}</li>
	<li *ngFor="let person of people">{{person.position}}</li>
</ul>

<!-- *ngIf -->
<p *ngIf="bool">如果条件为真,那么你可以看到这段文字,否则看不到</p>

<!-- ngClass -->

<style>
	.blue{ color: blue;}
	.red{ color: red;}
	.underline{ text-decoration: underline;}
</style>

directory.component.ts

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-directory',
  templateUrl: './directory.component.html',
  styleUrls: ['./directory.component.css'],
})
export class DirectoryComponent implements OnInit {
  
  classes = {'blue':true,'red':false;,'underline':false};

  bool = true;

  people = [
    {name:"Linus",position:"CIO"},
    {name:"Brin",position:"CDO"},
    {name:"Zuckerberg",position:"CBO"}
  ];

  constructer(private route:ActivatedRoute) {
  	
  }

  ngOnInit() {
    
  }
}
 类似资料: