软件开发综合实训是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.ts | appmodule定义,根模块的角度,讲述了如何装配的应用。现在就只有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.{app | spec}.json |
tslint.json | 额外Linting配置在ng lint运行中为TSLint合并到Codelyzer,Linting有助于让你的代码风格一致。 |
安装npm install -g typescript
编译tsc helloworld.ts
JavaScript和TypeScript对比
语言 | 类型 | 说明 |
---|---|---|
JavaScript | myVar = “String”;myVar = 28 | 语法正常,变量改变为数字28 |
TypeScript | myVar = “String”;myVar = 28 | TS明确类型,不允许 |
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>
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>
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() {
}
}