ng new my-app
ng serve --open
// 创建一个main组件, 系统为该组件命名为app-main供使用,
ng generate component main (简写 ng g c main)
ng g s
ng g c session/info/msg (在session文件下的info文件夹创建msg组件)
<ul>
<li class="her" *ngFor="let hero of hero" (click)="onSelect(hero)">
<span>{{hero.id}}span>
<span>{{hero.name}}span>
li>
ul>
export class HerosComponent implements OnInit {
constructor() { }
hero = HEROES
selectedHero: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
console.log('hero', hero)
}
ngOnInit() {
console.log('生命钩子函数-ngOnInit')
}
}
<ng-template ngFor let-item [ngForOf]="userAllMsgArr" let-i="index" [ngForTrackBy]="trackByAllMsg" >
<div *ngIf="item.isTrue">
<li>{{i}}---{{item.name}}li>
div>
ng-template>
<div class="user" *ngFor="let item of userList" #list (click)="clickUser(item, list)">div>
<div class="user" *ngFor="let item of userList" #list (click)="clickUser(item, $event)">div>
<div class="msg-box" #msgBox>div>
import { Component, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent implements OnInit {
@ViewChild('msgBox') msgBox: ElementRef
constructor() { }
testFn(dm): void {
this.msgBox.nativeElement
}
}
<div class="hero" *ngIf="selectedHero">div>
// box.component.html
<div class="box">
<h3>box componenth3>
<app-box-top [num]=100>app-box-top>
div>
// box-top.component.html
<div class="box-top">
<h4>box-top componenth4>
<h4>{{num}}h4>
div>
import { Component, OnInit, Input, Output } from '@angular/core';
@Component({
selector: 'app-box-top',
templateUrl: './box-top.component.html',
styleUrls: ['./box-top.component.css']
})
export class BoxTopComponent implements OnInit {
// 声明对外暴露的接口, 用于接受父组件的数据源输入, 必须是Number类型
@Input() num: Number;
constructor() { }
ngOnInit() {
}
}
<div class="box-top">
<div [ngStyle]="setStyle()">ngStylediv>
div>
export class BoxTopComponent implements OnInit {
constructor() { }
setStyle() {
return {
'font-size': '22px',
'color': 'blue'
}
}
ngOnInit() {
}
}
必须先在根模块中引入FormsModule
import { FormsModule } from '@angular/forms';
@NgModule({
// ...
imports: [
FormsModule
],
})
export class AppModule { }
<div class="box-top">
<h4>{{person}}h4>
<input type="text" value="person" [(ngModel)]="person">
div>
export class BoxTopComponent implements OnInit {
constructor() { }
person: string = 'tom'
ngOnInit() {}
}
<div class="box-top">
<h4 [ngClass]="{box-title: sty.hasTitle}">设置类h4>
div>
<div class="box">
<div (click)="runBoxTopClick()">调用子组件box-top的testClick方法div>
div>
import { Component, OnInit, ViewChild } from '@angular/core';
import { BoxTopComponent } from '../box-top/box-top.component'
@Component({
selector: 'app-box',
templateUrl: './box.component.html',
styleUrls: ['./box.component.css']
})
export class BoxComponent implements OnInit {
@ViewChild(BoxTopComponent) boxTopFn: BoxTopComponent;
constructor() { }
runBoxTopClick() {
console.log('box调用子组件box-top里的testClick方法')
this.boxTopFn.testClick()
}
ngOnInit() {
}
}
import { Component, OnInit, Input, Output } from '@angular/core';
@Component({
selector: 'app-box-top',
templateUrl: './box-top.component.html',
styleUrls: ['./box-top.component.css']
})
export class BoxTopComponent implements OnInit {
constructor() { }
testClick() {
console.log('box-top')
}
ngOnInit() {
}
}
<div class="box">
<h3>boxh3>
<app-box-child select="[name=middle]">
<div class="middle">
<h4>嵌入内容到子组件, 此h4会嵌入到子组件中h4>
div>
<div class="bottom">
<h4>嵌入内容到子组件, 此内容不会到子组件中, 不会显示在页面中h4>
div>
<div name="top">
<h5>嵌入内容到子组件, 此h5会嵌入到子组件中h5>
div>
app-box-child>
div>
<div class="box-child">
<ng-content select="[name=top]">ng-content>
<ng-content select=".middle">ng-content>
div>
// [value] input值的绑定
<input type="number" name="num" [value]="person.num" (input)="inputChange($event)" />
person: Object = {
num: 0
}
inputChange(e) :void {
this.person.num = e.target.value
}
import { FormsModule } from @angular/forms;
// 在所有模块中都能使用
@NgModule({
FormsModule
})
<div class="pip">
<span>{{this.mydate | date: "yyyy-mm-dd hh:mm:ss"}}span>
<button (click)="getNowTime()">获取当前时间button>
div>
export class MainComponent implements OnInit {
constructor() { }
mydate: Object
getNowTime(): void {
this.mydate= new Date()
}
}
ng generate pipe scoresLevel
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'scoresLevel'
})
export class ScoresLevelPipe implements PipeTransform {
transform(value: Number): String {
console.log('scoresLevel-----', value)
if (value >= 90 && value <= 100) {
return 'A';
} else if (value >= 80 && value < 90) {
return 'B';
} else if (value >= 70 && value < 80) {
return 'C';
} else if (value < 70) {
return 'D';
}
}
}
<div class="diy-pip">
<div>{{myScores | scoresLevel}}div>
<input type="number" [(ngModel)]="myScores" >
div>
import { Component, OnInit, Input, EventEmitter } from '@angular/core';
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
constructor() { }
myScores: Number = 88
}
import { Injectable } from '@angular/core';
export class CommonService {
products: object[] = []
addProducts(info: Object): void {
this.products.push(info)
}
clearProducts(): void {
this.products = []
}
}
<div class="add-product">
<input type="text" [(ngModel)]="product.title" placeholder="名称">
<input type="text" [(ngModel)]="product.des" placeholder="详情">
<input type="text" [(ngModel)]="product.price" placeholder="价格">
<input type="text" [(ngModel)]="product.addr" placeholder="产地">
<button (click)="addProducts()">addProductsbutton>
div>
<app-main>app-main>
import { Component } from '@angular/core';
import { CommonService } from './commonService'
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [CommonService]
})
export class AppComponent {
product: Object = { title: '', des: '', price: '', addr: '' }
constructor( private _CommonService: CommonService) {}
addProducts(): void {
this._CommonService.addProducts(this.product)
console.log('-app-', this._CommonService.products)
}
}
<div class="common-service">
<button (click)="getProductList()">获取商品列表button>
<li *ngFor="let item of productList">
<span>{{item.title}}span> -
<span>{{item.des}}span> -
<span>{{item.price}}span> -
<span>{{item.addr}}span>
li>
div>
import { Component, OnInit, Input, EventEmitter } from '@angular/core';
import { CommonService } from '../commonService'
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
productList: Array<object>
constructor( private _CommonService: CommonService) { }
getProductList(): void {
this.productList = this._CommonService.products
}
}
npm install --save rxjs rxjs-compat
ng generate service ajax
import { HttpModule } from '@angular/http';
@NgModule({
imports: [
HttpModule
],
})
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/Rx';
const url_getStudents: string = 'https://127.0.0.1:3000/studentsList'
@Injectable({
providedIn: 'root'
})
export class AjaxService {
constructor( private _http: Http ) { }
getPruductList(): Observable<any[]> {
return this._http.get(url_getStudents)
.map(((res) => {
console.log('res.json()', res.json())
return res.json()
}))
}
}
<div class="http">
<button (click)="getPruductList()">getbutton>
div>
import { Component, OnInit, Input, EventEmitter } from '@angular/core';
import { CommonService } from '../commonService'
import { AjaxService } from '../ajax.service'
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
constructor(
private _AjaxService: AjaxService
) { }
getPruductList(): void {
this._AjaxService.getPruductList().subscribe(contacts => {
console.log('contacts', contacts)
}, err => {
console.log('err', err)
})
}
}
ng generate service ajax
import { HttpModule } from '@angular/http';
@NgModule({
imports: [
HttpModule
],
})
import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import 'rxjs/Rx';
const url_addStudents: string = 'https://127.0.0.1:3000/add'
@Injectable({
providedIn: 'root'
})
export class AjaxService {
constructor( private _http: Http ) { }
addProductList(): Observable<any[]> {
// let headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded'})
let headers = new Headers({'Content-Type': 'application/json'})
let options = new RequestOptions({headers:headers})
return this._http.post(url_addStudents, {name: 'tom'}, options)
.map(((res) => {
console.log('res.json()----post', res.json())
return res.json()
}))
}
}
<div class="http">
<button (click)="addProductList()">postbutton>
div>
import { Component, OnInit, Input, EventEmitter } from '@angular/core';
import { AjaxService } from '../ajax.service'
@Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
constructor(
private _AjaxService: AjaxService
) { }
addProductList(): void {
this._AjaxService.addProductList().subscribe(contacts => {
console.log('contacts', contacts)
}, err => {
console.log('err', err)
})
}
}
(window as any).global = window;
import * as socketIo from "socket.io-client";
export class AppComponent {
io = socketIo
ngOnInit(): void {
console.log('--socket--', this.io)
}
}
export class ChatComponent implements OnInit {
@Input() userAllMsg: object
constructor() { }
ngOnInit() {}
ngOnChanges(changes: object): void {
if (this.userAllMsg) {
// 访问暂时不存在的对象时需要用[] 不能用点语法
this.userAllMsgArr = this.userAllMsg['userAllMsg']
}
}
}
ngOnChanges当前晋档@Input装饰器显示指定的变量变化时被调用
<div class="box">
<h2>boxh2>
<button (click)="addBoxNum()">改变numbutton>
<app-box-child [num]="boxNum">app-box-child>
div>
import { Component, OnInit, ViewChild } from '@angular/core';
import { BoxTopComponent } from '../box-top/box-top.component'
@Component({
selector: 'app-box',
templateUrl: './box.component.html',
styleUrls: ['./box.component.css']
})
export class BoxComponent implements OnInit {
@ViewChild(BoxTopComponent) boxTopFn: BoxTopComponent;
constructor() { }
addBoxNum(): void {
this.boxNum += 1
}
boxNum: Number = 12
ngOnInit() {
}
}
<div class="box-child">
<h4>父组件传过来的num: {{num}}h4>
div>
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-box-child',
templateUrl: './box-child.component.html',
styleUrls: ['./box-child.component.css']
})
export class BoxChildComponent implements OnInit {
@Input() num: Number;
ngOnChanges(data): void {
console.log('父元素传过来的值改变了', data)
}
constructor() { }
ngOnInit() {
}
}
[外链图片转存失败(img-2ZfkdrFe-1563117055663)(assets/ngOnChanges.gif)]
该方法内可用于获取数据, 类似于vue的created
import { Routes } from '@angular/router'
import { ListComponent } from './list/list.component'
export const rootRouterConfig: Routes = [
{path: 'list', component: ListComponent}
]
import { rootRouterConfig } from './app.routes'
import { NgModule, ModuleWithProviders } from '@angular/core';
import { RouterModule } from '@angular/router'
let rootRouteModule:ModuleWithProviders = RouterModule.forRoot(rootRouterConfig)
@NgModule({
imports: [
rootRouteModule
],
})
export class AppModule { }
<div class="route">
<h3>routeh3>
<a [routerLink]="['/list']">goto-lista>
<router-outlet>router-outlet>
div>
是否使用hash
let rootRouteModule:ModuleWithProviders = RouterModule.forRoot(
rootRouterConfig, {useHash: false}
)
// HashLocationStrategy策略
// useHash: true => http://localhost:4200/#/list
// PathLocationStrategy策略
// useHash: false => http://localhost:4200/list
被激活的路由自动赋予atv类
<div routerLinkActive="atv">
<a [routerLink]="['/list']">goto-lista>
div>
<div routerLinkActive="atv">
<a [routerLink]="['/detail']">goto-detaila>
div>
.atv {
background: red;
}
import { Router } from '@angular/router'
export class AppComponent {
constructor(
private _router: Router
) {
_router.navigateByUrl('/list')
}
}
<div class="route-fn" (click)="jsGoToList()">js-routediv>
import { Router } from '@angular/router'
export class AppComponent {
constructor(
private _router: Router
) {}
jsGoToList(): void {
this._router.navigateByUrl('/list?num=8') // localhost:4200/#/list?num=8
// 或者this._router.navigate(['/list'], {queryParams: {num: 8}}) localhost:4200/#/list?num=8
}
}
// 实现路由带参数
localhost:4200/#/list?num=8
// 按钮
<a [routerLink]="['/list']" [queryParams] = "{num: 10}">goto-list</a>
// js
this._router.navigate(['/list'], {queryParams: {num: 8}})
this._router.navigateByUrl('/list?num=8')
<div routerLinkActive="atv">
to-detaila>
div>
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'
@Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css']
})
export class DetailComponent implements OnInit {
constructor(
private _activatedRoute: ActivatedRoute
) { }
ngOnInit() {
this._activatedRoute.queryParams.subscribe(params => {
console.log(params) // {num: "10", from: "a", addr: "usa"}
})
}
}
import { Routes } from '@angular/router'
import { DetailComponent } from './detail/detail.component'
import { InfoComponent } from './info/info.component'
export const rootRouterConfig: Routes = [
{path: 'detail', component: DetailComponent, children: [
// path为空表示默认显示的路由
// {path: '', component: Info2Component}
{path: 'info', component: InfoComponent}
]}
]
<div class="detail">
<h3>detail-componenth3>
goto-detail-infoa>
<router-outlet>router-outlet>
div>
同一个页面只能有一个router-outlet , 可以有多个附属路由
import { Routes } from '@angular/router'
import { DetailComponent } from './detail/detail.component'
import { InfoComponent } from './info/info.component'
export const rootRouterConfig: Routes = [
{path: 'detail', component: DetailComponent, children: [
{path: 'info', component: InfoComponent},
{path: 'addr', component: AddrComponent, outlet='card'},
{path: 'age', component: AgeComponent, outlet='card'}
]}
]
<div class="detail">
<h3>detail-componenth3>
goto-detail-infoa>
<router-outlet>router-outlet>
<router-outlet name="card">router-outlet>
div>
新的 CLI 命令ng add 将使你的项目更容易添加新功能。ng add使用软件包管理器来下载新的依赖包并调用安装脚本,它可以通过更改配置和添加额外的依赖包(如 polyfills)来更新你的应用。
你可在新的ng new应用程序中尝试以下动作:
我们在组件需要某个服务的实例时,不需要手动创建这个实例,只需要在构造函数的参数中指定这个实例的变量,以及这个实例的类,然后angular会根据这个类的名字找到providers属性中指定的同名的provide,再找到它对应的useclass,最终自动创建这个服务的实例。
使用面向对象的代码制造一辆车, 下面代码中的汽车一旦制造, 发动机, 门, 车身都不能更改
import Engine from './engine';
import Doors from './doors';
import Body from './body';
export default class Car {
engine: Engine;
doors: Doors;
body: Body;
constructor() {
this.engine = new Engine();
this.body = new Body();
this.doors = new Doors();
}
run() {
this.engine.start();
}
}
解决依赖问题, 下面代码再车被制造出来之后仍然可以更改汽车的发动机, 车身, 门
let engine = new NewEngine();
let body = new Body();
let doors = new Doors();
this.car = new Car(engine, body, doors);
this.car.run();
angular的依赖注入
@Injectable()
export default class Car {
constructor(
private engine: Engine,
private body: Body,
private doors: Doors) {}
run() {
this.engine.start();
}
};
Rxjs是一种针对异步数据流的编程。它将一切数据,包括HTTP请求,DOM事件或者普通数据等包装成流的形式,然后用强大丰富的操作符对流进行处理,能以同步编程的方式处理异步数据,并组合不同的操作符来所需要的功能。
const ob = http$.getSomeList(); //getSomeList()返回某个由`Observable`包装后的http请求
ob.subscribe((data) => console.log(data));
ob.subscribe({
next: d => console.log(d),
error: err => console.error(err),
complete: () => console.log('end of the stream')
})
// 直接给subscribe传入一个函数会被当做是next函数。这个完整的包含3个函数的对象被称为observer(观察者),表示的是对序列结果的处理方式。next表示数据正常流动,没有出现异常;error表示流中出错,可能是运行出错,http报错等等;complete表示流结束,不再发射新的数据。在一个流的生命周期中,error和complete只会触发其中一个,可以有多个next(表示多次发射数据),直到complete或者error。
let reg = new RegExp("/::\\)|/::~|/::B|/::\\||/:8-\\)|", 'g');
reg.compile(reg)
// error TS2554: Expected 0 arguments, but got 1.
有时候你会遇到这样的情况,你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript会假设你,程序员,已经进行了必须的检查。
类型断言有两种形式:
let someValue: any = "this is a string";
let strLength: number = (someValue).length;
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
let reg = new RegExp("/::\\)|/::~|/::B|/::\\||/:8-\\)|", 'g');
(<any>reg).compile(reg)
里面内容是严格json格式, 不能出现注释不然会报错
Unexpected token / in JSON at position
npm install --save @angular/material @angular/cdk
npm install --save @angular/animations
npm install --save hammerjs
// app.module
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MaterialModule } from './material.module';
@NgModule({
imports: [
MaterialModule
],
})
export class AppModule { }
// material.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material';
import {MatTableModule} from '@angular/material/table';
@NgModule({
imports: [
MatButtonModule,
MatTableModule
// 要使用的组件
],
exports: [
MatButtonModule,
MatTableModule
// 要使用的组件
],
})
export class MaterialModule { }
// main.ts
import 'hammerjs';
// style.css
@import "~@angular/material/prebuilt-themes/indigo-pink.css";
<mat-table [dataSource]="orderList" class="mat-elevation-z8">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef class="print-order-num"> 姓名 mat-header-cell>
<mat-cell *matCellDef="let element" class="print-order-num"> {{element.name}} mat-cell>
ng-container>
<ng-container matColumnDef="addr">
<mat-header-cell *matHeaderCellDef> 地址 mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.addr}} mat-cell>
ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns">mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;">mat-row>
mat-table>
// 用于显示列
displayedColumns: string[] = ['name', 'addr'];
orderList: Array<object> = [
{name: 'tom', addr: 'usa'},
{name: 'jack', addr: 'uk'}
]