angular学习
环境-工具
1:先确保安装了nodejs和npm
Nodejs
Angular 需要 Node.js 版本 10.9.0 或更高版本。要检查你的版本,请在终端/控制台窗口中运行 node -v 。
windows更新版本不能通过网上说的安装n模块更新,只能重新下载新版的nodejs重新安装覆盖.
npm 包管理器
Angular、Angular CLI 和 Angular 应用都依赖于 npm 包中提供的特性和功能。要想下载并安装 npm 包,你必须拥有一个 npm 包管理器。
本搭建指南使用 npm 客户端命令行界面,Node.js 已经默认安装了它。
要检查你是否安装了 npm 客户端,请在终端/控制台窗口中运行 npm -v 。
cnpm(淘宝的镜像)
一般的项目通过npm install(npm 是干啥的等会再说)项目时不会有什么错误,只会时间比较长,这时候有人推荐用cnpm,下面是如何安装cnpm:
npm install -g cnpm --registry=https://registry.npm.taobao.org
2.安裝angualr cli
你可以使用 Angular CLI 来创建项目、生成应用和库代码,以及执行各种持续开发任务,比如测试、打包和部署。 https://www.angular.cn/guide/setup-local#step-1-install-the-angular-cli
- 查看angualr的版本命令:ng --version
- 卸载当前版本的angular: https://www.jianshu.com/p/268dd2a94471
- 我装的最新版用的是:npm install -g @angular/cli
3.工具
VSCode的angular插件
- Angular 7 Snippets:Angular语法填充(标签)
Angular Files:生成Angular的文件模板(Component、Module、Pipe等等)
Angular Follow Selector:文件跳转(Component跳转到html、scss文件)
Angular Language Service:引用填充和跳转到定义(html中进行引用补全)
新建angualr项目
1.新建项目angualrDemo
ng new angualrDemo --skip-install
–skip-install 跳过安装依赖
文件目录结构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PXXFVVfe-1672042949986)(C:\Users\19657\Desktop\新建文件夹\images\1.png)]
根组件app.module.ts 文件分析:
组件的组成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-16UVLBPl-1672042949987)(C:\Users\19657\Desktop\新建文件夹\images\2.png)]
自定义创建组价
ng g component commons/news(文件夹/组件名)
根组件使用自定义组件需要先import引入再declarations根组件中注册,最后在页面中使用组件的selector名称
启动项目:
ng serve 默认启动在端口4200
ng serve – open,启动并打开浏览器
ng serve --port 端口
基本语法
绑定数据
文本绑定:{{}}
绑定html
<span [innerHTML]="content"></span>
绑定属性
<div [title]="student"></div>
使用[]进行绑定
数据循环*ngFor
<div *ngFor="let item of list; let key=index;">{{ item }}</div>
条件判断*ngIf
<div *ngFor="let item of list; let key=index;">
<div *ngIf="item.status">{{item}}</div>
</div>
[ngSwitch] 和 *ngSwitchCase
<span [ngSwitch]="option">
<p *ngSwitchCase="1">
{{1}}
</p>
<p *ngSwitchCase="2">
{{2}}
</p>
<p *ngSwitchDefault>
{{3}}
</p>
</span>
事件绑定
普通事件:
<button (click)="clickFun()">点击按钮触发方法</button>
绑定键盘按下抬起事件:
<input (keydown)="onKeyDown()"></input>
<input (keyup)="onKeyUp()"></input>
事件对象
<button (click)="clickFun($event)">点击按钮触发方法</button>
<input (keydown)="onKeyDown($event)"></input>
<input (keyup)="onKeyUp($event)"></input>
ts 中: onKeyDown(e){
console.log(e)
}
双向事件绑定
针对表单
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XruUjMTY-1672042949988)(C:\Users\19657\Desktop\新建文件夹\images\3.png)]
<input type="text" [(ngModel)]="title" (keydown)="onKeyDown($event)">
public title:string = "vvv"
onKeyDown(e:any){
if(e.keyCode === 13){ // 13 是回车按键
console.log(this.title)
}
}
[ngClass]、[ngStyle]
<span [ngClass]="{'red': flage, 'blue': true}"></span>
<p [ngStyle]="{‘color’: 'red', 'width': pWidth}"></p>
管道
表单数据绑定
-
<input type="text" id="username" [(ngModel)]="peopleInfo.username" value="fonm_input" /> <input type="radio" value="1" name="sex" id="sex1" [(ngModel)]="peopleInfo.sex" /> <label for="sex1">男 </label> <input type="radio" value="2" name="sex" id="sex2" [(ngModel)]="peopleInfo.sex" /> <label for="sex2">女 </label> <select name="city" id="city" [(ngModel)]="peopleInfo.city"> <option [value]="item" *ngFor="let item of peopleInfo.cityList"> {{ item }} </option> </select> <span *ngFor="let item of peopleInfo.hobby; let key = index"> <input type="checkbox" [id]="'check' + key" [(ngModel)]="item.checked" /> <label [for]="'check' + key"> {{ item.title }}</label> </span> <textarea name="mark" id="mark" cols="30" rows="10" [(ngModel)]="peopleInfo.mark" ></textarea>
组件通信
1. 父组件传值(属性以及方法)给子组件
```js
父组件定义一个属性 title,方法 run
public title:string = ‘我是父组件的 title’
run(){ console.log(111) }
在子组件中绑定父组件的属性
<app-header [title]=“title” [run]=“run”>
子组件中引入 Input 装饰器
import { Component, OnInit, Input} from ‘@angular/core’
子组件业务 ts 的类中通过 Input 装饰器获取父组件传过来的属性(写在构造函数的前面)
@Input() title:string
@Input() run:any
#### 2. 把整个父组件传给子组件
```js
将整个父组件传递给子组件
<app-header [parent]="this"></app-header>
子组件中引入 Input 装饰器
import { Component, OnInit, Input} from '@angular/core'
子组件通过 Input 装饰器获取整个父组件
@Input parent:any
子组件中获取父组件的属性,执行父组件的方法
console.log(this.parent.title)
this.parent.run()
3.父组件中通过 ViewChild 获取子组件的属性及调用方法
1. 用 # 给子组件取个名字
<app-header #header></app-header>
2. 在业务逻辑里面引入 ViewChild
import { Component, OnInit, ViewChild } from '@angular/core';
3. 通过 ViewChild 装饰器获取子组件(写在类里面,构造函数上面)
@ViewChild('header') header:any
4. 获取子组件的属性,调用子组件中的方法
console.loga(this.header.title)
this.header.run()
4. Output 和 EventEmitter 实现父子组件的通信
子组件中引入 Output 装饰器和 EventEmitter
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
子组件中通过 Output 装饰器定义一个广播因子 outer,子组件触发自身方法将广播因子播散出去
@Output() private outer:any = new EventEmitter()
sentToParent(){
this.outer.emit('我是子组件的数据')
}
父组件中捕获广播因子,触发父组件自身的方法 run,$event 作为传递的参数
<app-news (outer)="run($event)"></app-news> (子组件标签)
run(e:any){
console.log(e) // e: 我是子组件的数据
}
生命周期函数
* ngOnChanges() 主要是用在父子组件传值中,父组件向子组件传值的时候 以及 父组件改变传值的数据的时候会触发该函数
* ngOnInit() 一般用来请求数据
ngDoCheck()
ngAfterContentInit() 组件渲染完成之后触发
ngAfterContentChecked()
* ngAfterViewInit() 在该函数中一般进行DOM操作
ngAfterViewChecked()
* ngOnDestroy() 组件销毁时触发该函数
服务
创建服务
ng g service (指定路径/)服务名称
1.在组件中import
2.在装饰器中引入
3.在组件中import使用
4.在组件构造函数中定义并使用
数据持久化
// storage.service.ts
// localStorage 实例
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
constructor() { }
save(key:string, val:any){
localStorage.setItem(key, JSON.stringify(val))
}
get(key:string){
let v = localStorage.getItem(key)
return v ? JSON.parse(v) : null
}
delete(key:string){
localStorage.removeItem(key)
}
}
DOM操作
1.远程js dom操作
2.ViewChild
1. 在模板中用 # 给 dom 起一个名字
<div #myBox>我是一个节点</div>
2. 在业务逻辑里面引入 ViewChild
import { Component, OnInit, ViewChild } from '@angular/core';
3. 通过 ViewChild 装饰器获取节点(写在类里面,构造函数上面)
@ViewChild('myBox') myBox:any
4. 在 ngAfterViewInit 生命周期函数中处理 dom
let node:any = this.myBox.nativeElement
node.style.color = 'red'
请求数据
1.get
1.
import { HttpClientModule } from '@angular/common/http'
...
imports: [ /* 配置当前模块运行依赖的其他模块 */
HttpClientModule
],
2.在组件中声明及构造函数中定义
import { HttpClient } from '@angular/common/http'
...
constructor(public http:HttpClient) { }
3.使用
getData(){
let api:any = ''
this.http.get(api).subscribe((res:any)=>{
console.log(res)
})
}
2.post
1.
import { HttpClientModule } from '@angular/common/http'
...
imports: [ /* 配置当前模块运行依赖的其他模块 */
HttpClientModule
],
2.在组件中声明及构造函数中定义
import { HttpClient, HttpHeaders } from '@angular/common/http'
...
constructor(public http:HttpClient) { }
3.使用
doLogin(){
let consthttpOptions:any = {
headers: new HttpHeaders({ 'Content-Type': 'application/json'})
}
let api:any = ''
let data:any = {'username': 'cty', 'age': 20}
this.http.post(api, data, consthttpOptions).subscribe((response)=>{
console.log(response)
})
}
3.jsonp
1.
import { HttpClientModule, HttpClientJsonpModule } from '@angular/common/http'
...
imports: [ /* 配置当前模块运行依赖的其他模块 */
HttpClientModule,
HttpClientJsonpModule
],
2.
import { HttpClient } from '@angular/common/http'
...
constructor(public http:HttpClient) { }
3.
getJsonpData(){
let api:any = ''
this.http.jsonp(api, 'callback').subscribe((res:any)=>{
console.log(res)
})
}
4.第三方库
axios
import axios from 'axios'
getAxiosData(){
let api:any = ''
let stream:any = new Observable(subscriber=>{
axios.get(api).then((res:any)=>{
subscriber.next(res)
}).catch((err)=>{
subscriber.error('err')
})
})
stream.subscribe((res:any)=>{
console.log(res)
})
}
路由
1.定义并使用
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
// 引入组件
import { HomeComponent } from './components/home/home.component';
import { NewsComponent } from './components/news/news.component';
// 编写路由路径以及路径对应的组件
const routes: Routes = [
{path: 'home', component: HomeComponent},
{path: 'news', component: NewsComponent},
// 匹配不到路由的时候加载的组件 或者跳转的路由 默认的路由
{path: '**', redirectTo: 'home'}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
② 路由组件将动态加载到 <router-outlet></router-outlet> 中,通过 routerLink 映射到对应的路由中
routerLinkActive="active" 调整路由选种样式 (.active{ color : red; })
<header class="header">
<a [routerLink]="['/home']" routerLinkActive="active">Home</a>
<button routerLink='/news' routerLinkActive="active">News</button>
</header>
<router-outlet></router-outlet>
2.路由传参
get传值:
1.传
<div [routerLink]="['/home']" routerLinkActive="active" [queryParams]="{aid: 'home'}">Home</div>
<div routerLink='/news' routerLinkActive="active" [queryParams]="{cty: 'news'}">News</div>
2.接收
// 引入 ActivatedRoute 模块
import { ActivatedRoute } from '@angular/router';
// 构造函数中声明 route
constructor(public route: ActivatedRoute) {}
// 方法中获取 传过来的参数
this.route.queryParams.subscribe((params:any)=>{
console.log(params)
})
动态路由传值
1.路由定义
const routes: Routes = [
{path: 'news/:cty', component: NewsComponent},
];
2.传参
<div [routerLink]="['/news/', '3333']" routerLinkActive="active">News</div>
3.接收
// 引入 ActivatedRoute 模块
import { ActivatedRoute } from '@angular/router';
// 构造函数中声明 route
constructor(public route: ActivatedRoute) {}
// 方法中获取 传过来的参数
this.route.params.subscribe((data:any)=>{
console.log(data)
})
3.事件传参
get
1.引入
import { Router, NavigationExtras } from '@angular/router';
2.声明及调用
constructor(public router: Router) { }
let queryParams: NavigationExtras = {
queryParams: {cty: 25}
}
this.router.navigate(['/home/'], queryParams)
动态
1.引入
import { Router } from '@angular/router';
2.声明及调用
constructor(public router: Router) { }
// 数组中第二个元素是动态路由的参数值,普通路由不用写第二个元素
this.router.navigate(['/news/', '12333'])
this.router.navigate(['/home'])
路由守卫
RXJS
初识:
RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。
https://www.wenjiangs.com/doc/rxjs-concepts-operator-imports
概念
combineLatest
Subject
Observable
of
throwError
never
Subscription
ReplaySubject
forkJoin
BehaviorSubject
操作符
takeUntil
map
catchError
mergeMap
debounceTime
filter
map
switchMap
distinctUntilChanged
delay
er: Router) { }
// 数组中第二个元素是动态路由的参数值,普通路由不用写第二个元素
this.router.navigate([‘/news/’, ‘12333’])
this.router.navigate([‘/home’])
### 路由守卫
### RXJS
初识:
RxJS 是一个库,它通过使用 observable 序列来编写异步和基于事件的程序。它提供了一个核心类型 Observable,附属类型 (Observer、 Schedulers、 Subjects) 和操作符 (map、filter、reduce、every, 等等),这些数组操作符可以把异步事件作为集合来处理。
https://www.wenjiangs.com/doc/rxjs-concepts-operator-imports
#### 概念
combineLatest
Subject
Observable
of
throwError
never
Subscription
ReplaySubject
forkJoin
BehaviorSubject
#### 操作符
takeUntil
map
catchError
mergeMap
debounceTime
filter
map
switchMap
distinctUntilChanged
delay