Angular学习小结
本文主要讲解ANgular在Windows平台的环境搭建。
安装Node.JS
-
官网下载稳定版本的node.js:https://nodejs.org/en/
-
安装对话框一路默认下一步,当然,可以按需修改安装路径。
-
安装完成后会自动将Node.JS的根目录添加到环境变量,读者可以自行查询。
-
在nodejs根目录,创建node_global,node_cache文件夹
-
以管理人员身份运行CMD。输入如下命令:
# 根据实际安装路径更改路径!
npm config set prefix "D:\DevelopmentToolRoot\WebFront\nodejs\node_global"npm config set cache "D:\DevelopmentToolRoot\WebFront\nodejs\node_cache"
-
将node_global、node_cache所在路径添加到path环境变量中
-
全局安装最常用的 express 模块
npm install express -g
- 配置淘宝镜像并安装cpm :
npm config set registry https://registry.npmmirror.com# 1. 注意修改nodejs安装目录的访问权限,让所有用户都能读写执行。
# 如果之前下载过nodejs,注意删除系统user目录下的package-lock.json文件
# npm install cnpm@7.1.1 -g
npm install -g cnpm
- 可以使用配置查看命令,查看配置是否成功:
npm config ls
安装Angular
- 首先卸载已经安装的版本:
# 老版本
npm uninstall -g html" title=angular>angular-cli
npm uninstall --save-dev html" title=angular>angular-cli# 新版本
npm uninstall -g @html" title=angular>angular/cli# 清空缓存
npm cache verify # npm cache clean --force
- 开始安装,报权限不允许的错误就使用管理员的方式打开cmd!
# cnpm install -g @html" title=angular>angular/cli@8.2.2
cnpm install -g @html" title=angular>angular/cli@latest
- 检查是否安装成功
ng help
- 项目创建
# 新建一个Angular项目,默认会执行np install
ng new projectName# 只创建不安装ng new projectName --skip-installcd projectName# npm install、yarn install
cnpm install
- 项目编译&启动
ng serve --open
- 在浏览器键入:http://localhost:4200/,可看到欢迎页面
常见报错:
html" title=angular>angular 6中使用socket.io报错:global is not define
在src/polyfills.ts中添加
html" title=typescript>typescript">(window as any).global = window;
创建一个组件
在项目根目录下使用如下命令:
D:\root\WorkSpace\AngularRoot\Start>ng g component component/news
CREATE src/app/component/news/news.component.html (19 bytes)
CREATE src/app/component/news/news.component.spec.ts (614 bytes)
CREATE src/app/component/news/news.component.ts (262 bytes)
CREATE src/app/component/news/news.component.scss (0 bytes)
UPDATE src/app/app.module.ts (398 bytes)
vscode终端执行ng serve报错:
ng : 无法加载文件 C:\Users\root\AppData\Roaming\npm\ng.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的 about_Execution_Policie
s。
所在位置 行:1 字符: 1
+ ng serve
+ ~~
在搜索框搜索:Windows PowerShell ISE,执行如下命令并选A(全是)即可解决
set-ExecutionPolicy RemoteSigned
html" title=angular>angular不建议使用dom操作来改变class
使用Forms模块
在src/app/app.module.ts文件夹中添加:
html" title=typescript>typescript">// ...
import { FormsModule } from '@html" title=angular>angular/forms';@NgModule({imports: [// ...FormsModule],})
html 如下:
html"><div><form class="form" [formGroup]="infoForm"><ng-container><div formArrayName="infos"><div *ngFor="let info of infos.controls; let i = index"><ng-container [formGroupName]="i"><label>{{ info.get("name").value}}</label><input type="text" formControlName="value" [id]="i"></ng-container></div></div><button (click)="onSubmit()">保存</button></ng-container></form>
</div>
ts代码如下:
html" title=typescript>typescript">export class FormComponent implements OnInit {// fb:FormBuilder;constructor(private fb:FormBuilder) { // this.fb = fb;}infoForm = this.fb.group ({infos: this.fb.array([]),});get infos(): FormArray {return this.infoForm.get('infos') as FormArray;}ngOnInit() {const fm = this.fb.group({id: 1,name: "aaa",value: "aiaiai",});this.infos.push(fm);const fm1 = this.fb.group({id:2,name:"bbb",value:"bibibi",});this.infos.push(fm1);const fm2 = this.fb.group({id:3,name:"ccc",value:"cicici",});this.infos.push(fm2);var playerInterval_dvp = setInterval(() => {console.log("aaa")});}onSubmit(){console.log(this.infos.at(1).get('name').value);console.log((this.infos.at(1)))console.log((this.infos.at(1).value))console.log((this.infos.at(1).value as MyInfoInterface))console.log((this.infos.at(1).value as MyInfoInterface).value)}}export interface MyInfoInterface {id: number;name: string;value: string;
}
点击按钮后,结果如下:
创建一个服务
ng g service service/storage
在src/app/app.module.ts文件夹中添加:
html" title=typescript>typescript">import { StorageService } from './service/storage.service';@NgModule({// ...providers: [StorageService],// ...
})
在组件文件中添加:
html" title=typescript>typescript">import { StorageService } from '../../service/storage.service';export class SearchComponent implements OnInit {public keyword:string="电脑";public history:any[]=[];storage:StorageService;constructor(storage:StorageService) {this.storage = storage;var hi = this.storage.get("history");if (hi) {this.history = hi;}}ngOnInit() {}
}
DOM操作
DOM操作最好在ngAfterViewInit函数中进行,ngOnInit中操作的话,可能一些dom还没有加载完成导致获取不到DOM
在html" title=angular>angular中,操作dom的方式有两种:使用原生js和使用ViewChild
html"><p #myfirstdom>domopt works!</p>
html" title=typescript>typescript">import { Component, OnInit, ViewChild} from '@html" title=angular>angular/core';@Component({selector: 'app-domopt',templateUrl: './domopt.component.html',styleUrls: ['./domopt.component.scss']
})
export class DomoptComponent implements OnInit {@ViewChild("myfirstdom", {static:true}) myfirstdom:any;constructor() { }ngOnInit() {}ngAfterViewInit(){console.log(this.myfirstdom);this.myfirstdom.nativeElement.innerHTML = "aaa";}
}
父子组件传值
方式一:
数据、函数、父组件本身都能通过该方法传递。
父组件中定义:
html" title=typescript>typescript">export class NewsComponent implements OnInit {public title:string = "新闻";@ViewChild("myheader", {static:true}) header:any;constructor() { }ngOnInit() {}}
html"><app-header #myheader [title]="title"></app-header>
子组件中定义:
html" title=typescript>typescript">import { Component, OnInit, Input} from '@html" title=angular>angular/core';export class HeaderComponent implements OnInit {@Input() title:any;constructor() {}ngOnInit() {}
}
方式二:
子组件通过事件驱动的方式给父组件发消息。
子组件配置:
html" title=typescript>typescript">import { Component, OnInit, Input, Output, EventEmitter} from '@html" title=angular>angular/core';export class HeaderComponent implements OnInit {@Output() outer = new EventEmitter();constructor() {console.log(this.dt)}ngOnInit() {this.mvvm="初始值"}sendParent(){console.log("header的sendParent方法");this.outer.emit("header的sendParent");}
}
父组件配置:
html"><app-header (outer)="run($event)"></app-header>
html" title=typescript>typescript">import { Component, OnInit, ViewChild } from '@html" title=angular>angular/core';export class NewsComponent implements OnInit {constructor() { }ngOnInit() {}run(arg:any){alert("新闻中的run方法,还可以直接把整个新闻组件传给header!!!" + arg);}
}
异步处理
有两种:rxjs(observable)或者promise,主要介绍一下rxjs:
html" title=typescript>typescript">import {map,filter} from 'rxjs/operators'
import { RequestService } from '../../service/request.service'export class HomeComponent implements OnInit {request:RequestService;constructor(request:RequestService) {}ngOnInit() {var streamNum = this.request.getRxjsIntervalTimer();streamNum.pipe(filter((value)=>{if (Number(value)%2 == 0) {return true;}// console.log(Number(value)*Number(value));return false;}),map((val)=>{return Number(val)*Number(val);})).subscribe((value) => {console.log(value);});}}
RequestServer:
html" title=typescript>typescript">import { Observable } from 'rxjs';export class RequestService {constructor() { }getRxjsIntervalTimer(){var cnt = 0;return new Observable((observe)=>{setInterval(()=>{cnt++;// console.log(cnt);observe.next(cnt);}, 1000);});}
}
使用get、post请求
app.module.ts:
html" title=typescript>typescript">import { HttpClientModule } from '@html" title=angular>angular/common/http'@NgModule({// ...imports: [// ...HttpClientModule,]// ...
})
http如下:
html">
<button (click)="getRequest()">get请求</button><button (click)="postRequest()">post请求</button><button (click)="getJsonpData()">jsonp请求</button>
请求逻辑如下:
html" title=typescript>typescript">import { HttpClient, HttpHeaders } from '@html" title=angular>angular/common/http'export class RequesthttpComponent implements OnInit {http:HttpClient;constructor(http:HttpClient) {this.http = http;}ngOnInit() { }getRequest(){this.http.get("http://a.itying.com/api/productlist").subscribe((value)=>{console.log(value);});}postRequest() {var httpOptions = { headers: new HttpHeaders({"Content-Type": "application/json"}) };this.http.post("www.baidu.com", {"username":"zhangsan", "password":"123"}, httpOptions).subscribe((data)=>{console.log(data);});}getJsonpData(){this.http.jsonp("http://a.itying.com/api/productlist", "callback").subscribe((value)=>{console.log(value);}); }
}
路由
在app-routing.module.ts可配置静态路由:
html" title=typescript>typescript">import { NewsComponent } from './components/news/news.component';
import { MovieComponent } from './components/movie/movie.component';
import { GameComponent } from './components/game/game.component';
import { ContentComponent } from './components/content/content.component';const routes: Routes = [{path:"news",component: NewsComponent,},{path:"movie",component: MovieComponent,},{path:"game",component: GameComponent,},{path:"content",component: ContentComponent,},{path:"**",component: NewsComponent,},
];
加routerLinkActive可实现激活选中效果
html"><a [routerLink]="'/news'" routerLinkActive="active">新闻</a>
<a [routerLink]="'/movie'" routerLinkActive="active">电影</a>
<a [routerLink]="'/game'" routerLinkActive="active">游戏</a>
组件路由并传参:
get路由:
html" title=typescript>typescript">{path:"content",component: ContentComponent,}
父:
html"><p>news works!</p><ul><li *ngFor="let item of list; let i=index;"><a [routerLink]="'/content'" [queryParams]="{aid:i}">{{i}} === {{item}}</a></li>
</ul>
子:
html" title=typescript>typescript">import { ActivatedRoute } from '@html" title=angular>angular/router';export class ContentComponent implements OnInit {router:ActivatedRoute;constructor(router:ActivatedRoute) {this.router = router;}ngOnInit() {this.router.queryParams.subscribe((value)=>{console.log(value);});}}
动态路由:
html" title=typescript>typescript">{path:"content/:aid",component: ContentComponent,}
父:
html"><ul><li *ngFor="let item of list; let i=index;"><a [routerLink]="['/content/', i]">{{i}} === {{item}}</a></li>
</ul>
子:
html" title=typescript>typescript">import { ActivatedRoute } from '@html" title=angular>angular/router';export class ContentComponent implements OnInit {router:ActivatedRoute;constructor(router:ActivatedRoute) {this.router = router;}ngOnInit() {this.router.params.subscribe((value)=>{console.log(value);});}}
js 动态路由:
app-routing.module.ts:
html" title=typescript>typescript">{path:"content/:aid",component: ContentComponent,}
父
html" title=typescript>typescript">import { Router } from '@html" title=angular>angular/router';export class NewsComponent implements OnInit {router:Router;constructor(router:Router) {this.router = router;}ngOnInit() {this.router.navigate(["/content", "123"]);}
}
子
html" title=typescript>typescript">import { ActivatedRoute } from '@html" title=angular>angular/router';export class ContentComponent implements OnInit {router:ActivatedRoute;constructor(router:ActivatedRoute) {this.router = router;}ngOnInit() {this.router.params.subscribe((value)=>{console.log(value);});}}
js get路由:
html" title=typescript>typescript">{path:"content",component: ContentComponent,}
父:
html" title=typescript>typescript">import { Router, NavigationExtras } from '@html" title=angular>angular/router';export class NewsComponent implements OnInit {router:Router;constructor(router:Router) {this.router = router;}ngOnInit() {let params:NavigationExtras = {queryParams:{aid:"123"},fragment:"anchor"}this.router.navigate(["/content"], params);}
}
子:
html" title=typescript>typescript">
import { ActivatedRoute, Router } from '@html" title=angular>angular/router';export class ContentComponent implements OnInit {router:ActivatedRoute;constructor(router:ActivatedRoute) {this.router = router;}ngOnInit() {this.router.queryParams.subscribe((value)=>{console.log(value);});}}
路由嵌套:
根:
html"><a [routerLink]="'/news'" routerLinkActive="active">新闻</a>
<a [routerLink]="'/movie'" routerLinkActive="active">电影</a>
<a [routerLink]="'/game'" routerLinkActive="active">游戏</a>
<router-outlet></router-outlet>
app-routing.module.ts:
html" title=typescript>typescript">import { NgModule } from '@html" title=angular>angular/core';
import { Routes, RouterModule } from '@html" title=angular>angular/router';import { NewsComponent } from './components/news/news.component';
import { MovieComponent } from './components/movie/movie.component';
import { GameComponent } from './components/game/game.component';
import { ContentComponent } from './components/content/content.component';import { SystemsetComponent } from './components/movie/systemset/systemset.component';
import { SystemmaintainComponent } from './components/movie/systemmaintain/systemmaintain.component';
import { GamesetComponent } from './components/game/gameset/gameset.component';
import { GameupdateComponent } from './components/game/gameupdate/gameupdate.component';const routes: Routes = [{path:"news",component: NewsComponent},{path:"movie",component: MovieComponent,children:[{path:"systemset",component:SystemsetComponent,},{path:"systemmaintain",component:SystemmaintainComponent,},{path:"**",component:SystemsetComponent,}],},{path:"game",component: GameComponent,children:[{path:"gameset",component:GamesetComponent,},{path:"gameupdate",component:GameupdateComponent,},{path:"**",component:GamesetComponent,}],// },{// path:"content",// component: ContentComponent,// },{},{path:"content",component: ContentComponent,},{path:"**",component: NewsComponent,},
];@NgModule({imports: [RouterModule.forRoot(routes)],exports: [RouterModule]
})
export class AppRoutingModule { }
component/movie/movie.component.html
html"><p>movie works!</p><div class="content"><div class="left"><a [routerLink]="'/movie/systemset'" routerLinkActive="active">系统设置</a><br><br><a [routerLink]="'/movie/systemmaintain'" routerLinkActive="active">系统维护</a></div><div class="right"><router-outlet></router-outlet></div>
</div>
component/game/game.component.html
html"><p>game works!</p><div class="content"><div class="left"><a [routerLink]="'/game/gameset'" routerLinkActive="active">游戏设置</a><br><br><a [routerLink]="'/game/gameupdate'" routerLinkActive="active">游戏更新</a></div><div class="right"><router-outlet></router-outlet></div>
</div>
Subject和Observable的区别
Observable是Subject的特例,Subject是典型的发布订阅模式,可以将消息传递给多个订阅者,但是Observable只能一对一。
关于Renderer2的介绍
Renderer2 是 Angular 提供的一个用于操作 DOM 的服务类。它允许你在不直接访问浏览器的 DOM API 的情况下,通过抽象层安全地操作 DOM。Renderer2 是为了增强跨平台兼容性和更好的安全性而设计的,使得你的应用可以在浏览器、服务器端渲染(如 Angular Universal)以及 Web Workers 等不同的环境中运行。
关于dom操作
constructor(
private Re2: Renderer2,
private el: ElementRef,
// 其他依赖项…
) { }
直接访问宿主元素:
-
ElementRef 提供了对 Angular 组件、指令或 HTML 元素的宿主元素的直接引用。通过 el.nativeElement,你可以访问并操作该元素。例如,如果这个 ElementRef 是在一个组件中注入的,那么 el.nativeElement 指向该组件的根 DOM 元素。
与 Renderer2 结合使用: -
在你提供的构造函数中,ElementRef 通常与 Renderer2 一起使用。Renderer2 提供了一组安全的方法来操作 DOM,而 ElementRef 提供了操作的目标元素。
例如,在 ngOnInit 或其他方法中,你可能会通过 el.nativeElement 获取 DOM 元素,然后使用 Renderer2 对其应用样式、添加类或处理事件。
Data URL
例如,一个图像的Data URL可能看起来像这样:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
在这个例子中:
-
image/png 指定了MIME类型,表示这是一个PNG图像。
-
base64 表示数据是使用Base64编码的。
-
后面的长字符串是图像数据的Base64编码表示。
它允许将小文件直接嵌入到网页或网络请求中,而不需要从服务器上单独请求资源。Data URL 通常用于图像、字体、CSS、JavaScript 和其他小型文件,以减少HTTP请求的数量,从而提高页面加载速度。
本章完结