本系列笔记主要参考:
Angular学习视频
Angular官方文档
Angular系列笔记
特此感谢!
Angular 是一个基于 TypeScript 构建的开发平台。它包括:
Angular 是谷歌开发的一款开源的 web 前端框架,诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。
根据项目数统计 angular(1.x 、2.x 、4.x、5.x、6.x、7.x 、8.x、9.x)是现在网上使用量最大的框架。
Angular 基于 TypeScript 和 react、vue 相比 Angular 更适合中大型企业级项目。
npm install -g @angular/cli
ng --version //校验安装成功与否
相关配置可以参考如下链接:https://blog.csdn.net/weixin_43938259/article/details/104792233
ng new angularDemo
//或者这样,跳过下载依赖包,后续再下载
ng new angularDemo --skip-install
cd angularDemo
cnpm install
中间会提示是否创建带路由和样式编辑器,按需选取
终端输入如下命令,即可运行项目
cd angularDemo
ng serve --open
//或者这样
ng serve --o
//或者这样
ng serve
- node_modules 第三方依赖包存放目录
- e2e 端到端的测试目录 用来做自动测试的
- src 应用源代码目录
|- app 包含定义应用逻辑和数据的组件文件
|- app.component.ts 为应用的根组件定义逻辑,名为 AppComponent。当你向应用中添加组件和服务时,与这个根组件相关联的视图就会成为视图树的根。
|- app.component.html 定义与根组件 AppComponent 关联的 HTML 模板。
|- app.component.css 为根组件 AppComponent 定义了基本的 CSS 样式表。
|- app.component.spec.ts 为根组件 AppComponent 定义了一个单元测试。
|- app.module.ts 为应用的根组件定义逻辑,名为 AppComponent。定义了名为 AppModule 的根模块,它会告诉 Angular 如何组装应用。这里最初只声明一个 AppComponent。当你向应用中添加更多组件时,它们也必须在这里声明。
|- assets目录 资源目录,存储静态资源的 比如图片
|- environments 目录环境配置。Angular是支持多环境开发的,我们可以在不同的环境下(开发环境,测试环境,生产环境)共用一套代码,主要用来配置环境的
|- index.html 整个应用的根html,程序启动就是访问这个页面
|- main.ts 整个项目的入口点,Angular通过这个文件来启动项目
|- polyfills.ts 主要是用来导入一些必要库,为了让Angular能正常运行在老版本下
|- styles.css 主要是放一些全局的样式
|- tsconfig.app.json TypeScript编译器的配置,添加第三方依赖的时候会修改这个文件
|- tsconfig.spec.json 不用管
|- test.ts 也是自动化测试用的
|- typings.d.ts不用管
- .angular-cli.json Angular命令行工具的配置文件。后期可能会去修改它,引一些其他的第三方的包
比如jquery等
- karma.conf.js karma是单元测试的执行器,karma.conf.js是karma的配置文件
- package.json
这是一个标准的npm工具的配置文件,这个文件里面列出了该应用程序所使用的第三方依赖包。实际上我们在新建项目的时候,等了半天就是在下载第三方依赖包。下载完成后会放在node_modules这个目录中,后期我们可能会修改这个文件。
- protractor.conf.js 也是一个做自动化测试的配置文件
- README.md 说明文件
- tslint.json 是tslint的配置文件,用来定义TypeScript代码质量检查的规则,不用管它
// 1.创建组件 ng g component 目录名/组件名
ng g component components/header
// 2.使用组件 <app-header>app-header>
组件 ts 文件分析
import { Component, OnInit } from "@angular/core"; /*引入 angular 核心*/
@Component({
selector: "app-header" /*使用这个组件的名称*/,
templateUrl: "./header.component.html" /*html 模板*/,
styleUrls: ["./header.component.css"] /*css 样式*/,
})
export class HeaderComponent implements OnInit {
/*实现接口*/
constructor() {
/*构造函数*/
}
ngOnInit() {
/*初始化加载的生命周期函数*/
}
}
/*
public 共有 *(默认) 可以在这个类里面使用、也可以在类外面使用
protected 保护类型 他只有在当前类和它的子类里面可以访问
private 私有 只有在当前类才可以访问这个属性
*/
public title:string = 'this is a title'
<h1>{{title}}h1>
<div>1+1={{1+1}}div>
this.h = "这是一个 h2 用[innerHTML]来解析
";
<div [innerHTML]="h">div>
<div [id]="id" [title]="msg">调试工具看看我的属性div>
<ul>
<li *ngFor="let item of list">
{{item}}
li>
ul>
<ul>
<li *ngFor="let item of list;let i = index;">
{{item}} --{{i}}
li>
ul>
<ul>
<li template="ngFor let item of list">
{{item}}
li>
ul>
<p *ngIf="flag">这是 ngIF 判断是否显示p>
<p template="ngIf flag">这是 ngIF 判断是否显示p>
<ul [ngSwitch]="score">
<li *ngSwitchCase="1">已支付li>
<li *ngSwitchCase="2">订单已经确认li>
<li *ngSwitchCase="3">已发货li>
<li *ngSwitchDefault>无效li>
ul>
<button class="button" (click)="getData()">点击按钮触发事件button>
<button class="button" (click)="setData()">点击按钮设置数据button>
getData(){ /*自定义方法获取数据*/
//获取
alert(this.msg);
}
setData(){
//设置值
this.msg='这是设置的值';
}
键盘事件
<input type="text" (keyup)="keyUpFn($event)" />
keyUpFn(e){
console.log(e)
}
// e可能会报错,因为现阶段版本要求加上类型了,改成这样keyUpFn(e:any){...}
...
import { FormsModule } from '@angular/forms';
...
imports: [
BrowserModule,
FormsModule
],
<input type="text" [(ngModel)]="inputValue" /> {{inputValue}}
<div [ngClass]="{'red': true, 'blue': false}">这是一个 divdiv>
public flag=false;
<div [ngClass]="{'red': flag, 'blue': !flag}">这是一个 divdiv>
public arr = [1, 3, 4, 5, 6];
<ul>
<li *ngFor="let item of arr, let i = index">
<span [ngClass]="{'red': i==0}">{{item}}span>
li>
ul>
<div [ngStyle]="{'background-color':'green'}">你好 ngStylediv>
public attr='red';
<div [ngStyle]="{'background-color':attr}">你好 ngStylediv>
<p>{{today | date:'yyyy-MM-dd HH:mm:ss' }}p>
public today=new Date();
其他管道:http://bbs.itying.com/topic/5bf519657e9f5911d41f2a34
具体实施:https://www.bilibili.com/video/BV1X4411472m?p=5
参见 angularDemo4
通过使用服务,我们可以把应用程序中的通用代码提取出来,封装成一个可注入的类,并且可以在整个应用程序中共享使用。这样做有助于提高代码的复用性、可维护性和可测试性。同时也可以使组件更加专注于展示数据和处理用户交互。
import { Injectable } from "@angular/core";
/* @Injectable() 服务
注意,这个新的服务导入了 Angular 的 Injectable 符号,并且给这个服务类添加了 @Injectable() 装饰器。 它把这个类标记为依赖注入系统的参与者之一。
@Injectable() 装饰器会接受该服务的元数据对象,就像 @Component() 对组件类的作用一样。
*/
/* 默认情况下,Angular CLI 命令 ng generate service 会通过给 @Injectable() 装饰器添加 providedIn: 'root' 元数据的形式,用根注入器将你的服务注册成为提供者。 */
@Injectable({
providedIn: "root",
})
export class MyService {
private data: any;
getData() {
return this.data;
}
setData(data: any) {
this.data = data;
}
}
上面的代码定义了一个名为 MyService 的服务类,它包含了一个名为 data 的私有属性,以及两个公共方法:getData 和 setData。这个服务可以在应用程序中被注入到其他组件或服务中使用。
ng generate service my-service
这将在项目中创建一个名为“my-service”的服务,并在 app.module.ts 文件中注册它。
// 引入
import { MyService } from '../myservice.service';
// 注入服务
constructor(private myService: MyService) { }
getData(){
this.data = this.myService.getData()
}
PS:一般会在 ngOnInit()方法中调用 getData()这个方法,而不是在构造函数中
让构造函数保持简单,只做最小化的初始化操作,比如把构造函数的参数赋值给属性。构造函数不应该做任何事。它当然不应该调用某个函数来向远端服务(比如真实的数据服务)发起 HTTP 请求。
而是选择在 ngOnInit 生命周期钩子中调用 getData(),之后 Angular 会在构造出 该组件 的实例之后的某个合适的时机调用 ngOnInit()。
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root",
})
export class StorageService {
constructor() {}
set(key: string, value: any) {
localStorage.setItem(key, JSON.stringify(value));
}
get(key: string) {
return JSON.parse(localStorage.getItem(key) || "");
}
remove(key: string) {
localStorage.removeItem(key);
}
}
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { FormsModule } from "@angular/forms";
import { AppComponent } from "./app.component";
import { SearchComponent } from "./components/search/search.component";
import { TodolistComponent } from "./components/todolist/todolist.component";
//引入并且配置服务
import { StorageService } from "./services/storage.service";
FormsModule;
NgModule;
@NgModule({
declarations: [AppComponent, SearchComponent, TodolistComponent],
imports: [BrowserModule, FormsModule],
providers: [StorageService],
bootstrap: [AppComponent],
})
export class AppModule {}
<app-todolist>app-todolist>
<h2>todoListh2>
<div class="todolist">
<input
id="todoInput"
type="text"
[(ngModel)]="keyword"
(keyup)="doAdd($event)"
/>
<hr />
<h3>待办事项h3>
<ul>
<li *ngFor="let item of todolist,let key = index" [hidden]="item.status==1">
<input
type="checkbox"
[(ngModel)]="item.status"
(change)="checkBoxChange()"
/>{{item.title}} <button (click)="deleteTodo(key)">Xbutton>
li>
ul>
<h3>已完成事项h3>
<ul>
<li *ngFor="let item of todolist,let key = index" [hidden]="item.status==0">
<input type="checkbox" [(ngModel)]="item.status" />{{item.title}}
<button (click)="deleteTodo(key)">Xbutton>
li>
ul>
div>
h2 {
text-align: center;
}
.todolist {
width: 400px;
margin: 20px auto;
#todoInput {
margin-bottom: 20px;
width: 300px;
height: 32px;
}
li {
line-height: 60px;
}
}
/*
1、ng g service services/storage
2、app.module.ts 里面引入创建的服务 并且声明import { storageService } from './services/storage.serviceproviders:[storageService]
3、在用到的组件里面
//引入服务
import { storageService ] from '../../services/storage. service';
//初始化
constructor(public storage:StorageService){
console.log(storage);
}
*/
import { Component } from "@angular/core";
//引入服务
import { StorageService } from "src/app/services/storage.service";
@Component({
selector: "app-todolist",
templateUrl: "./todolist.component.html",
styleUrls: ["./todolist.component.scss"],
})
export class TodolistComponent {
public keyword: string = "";
public todolist: any[] = [];
//服务注入
constructor(public storage: StorageService) {
console.log(storage);
}
ngOnInit() {
//服务使用
var todolist = this.storage.get("todolist");
if (todolist) {
this.todolist = todolist;
}
}
doAdd(e: any) {
if (e.keyCode == 13) {
// console.log(this.keyword)
if (this.keyword !== "") {
if (!this.todoListHasKeyword(this.todolist, this.keyword)) {
this.todolist.push({ title: this.keyword, status: false });
//******数据持久化******
this.storage.set("todolist", this.todolist);
} else {
alert("数据已经存在!");
}
this.keyword = "";
}
}
}
deleteTodo(key: any) {
this.todolist.splice(key, 1);
//******数据持久化******
this.storage.set("todolist", this.todolist);
}
todoListHasKeyword(todolist: any[], keyword: any) {
let flag: boolean = false;
todolist.forEach((item) => {
if (item.title == keyword) flag = true;
});
return flag;
}
//监听多选框变化事件
checkBoxChange() {
console.log("change");
this.storage.set("todolist", this.todolist);
}
}
<div class="search">
<input type="text" [(ngModel)]="keyword" />
<button (click)="doSearch()">搜索button>
<hr />
<ul>
<li *ngFor="let item of historyList,let key = index">
{{item}}
<button (click)="deleteHistory(key)">xbutton>
li>
ul>
div>
2.search.component.scss
.search {
width: 400px;
margin: 20px auto;
input {
margin-bottom: 20px;
width: 300px;
height: 32px;
}
button {
height: 32px;
width: 80px;
}
li {
button {
width: 20px;
height: 20px;
border-radius: 50%;
}
}
}
import { Component } from "@angular/core";
//引入服务
import { StorageService } from "src/app/services/storage.service";
@Component({
selector: "app-search",
templateUrl: "./search.component.html",
styleUrls: ["./search.component.scss"],
})
export class SearchComponent {
public keyword: string = "";
public historyList: string[] = [];
constructor(public storage: StorageService) {
console.log(storage);
}
ngOnInit() {
//页面刷新会出发这个生命周期函数
var searchList = this.storage.get("searchList");
if (searchList) {
this.historyList = searchList;
}
}
doSearch() {
// console.log(this.keyword)
if (this.keyword !== "") {
// let index = this.historyList.indexOf(this.keyword)
// if(index != -1) this.historyList.splice(index,1)
// this.historyList.unshift(this.keyword)
if (this.historyList.indexOf(this.keyword) == -1) {
this.historyList.push(this.keyword);
//数据持久化
this.storage.set("searchList", this.historyList);
//重置keyword
this.keyword = "";
}
}
}
deleteHistory(key: number) {
// console.log(key)
this.historyList.splice(key, 1);
//数据持久化
this.storage.set("searchList", this.historyList);
}
}
ngAfterViewInit(){
let oBox1:any = document.getElementById('box1')
console.log(oBox1.innerHTML)
oBox1.style.color='blue'
}
// ViewChild获取DOM节点
// 1.模板中给dom起名字 #xxx
<div #myBox>
我是一个Dom节点
</div>
// 2.在业务逻辑里面引入ViewChild并获取节点
import { ViewChild } from '@angular/core';
// 写在类里面,获取dom节点
@ViewChild('myBox') mybox:any;
// 3.ngAfterViewInit生命周期函数获取Dom
//使用节点
console.log(this.mybox.nativeElement)
this.mybox.nativeElement.style.width = '100px'
this.mybox.nativeElement.style.height = '50px'
this.mybox.nativeElement.style.background = 'red'
console.log(this.mybox.nativeElement.innerHTML);
比如:
<app-header #header>app-header>
<hr />
<div #myBox>我是一个Dom节点div>
<button (click)="getChildRun()">获取子组件的方法button>
//引入ViewChild
import { Component, ViewChild } from "@angular/core";
@Component({
selector: "app-news",
templateUrl: "./news.component.html",
styleUrls: ["./news.component.scss"],
})
export class NewsComponent {
// 获取dom节点
@ViewChild("myBox") mybox: any;
// 获取一个组件
@ViewChild("header") header: any;
constructor() {}
ngOnInit(): void {}
ngAfterViewInit(): void {
console.log(this.mybox.nativeElement);
this.mybox.nativeElement.style.width = "100px";
this.mybox.nativeElement.style.height = "50px";
this.mybox.nativeElement.style.background = "red";
console.log(this.mybox.nativeElement.innerHTML);
// //调用子组件的方法
// this.header.run()
}
getChildRun() {
this.header.run();
}
}
<app-footer #footerChild>app-footer>
import { Component, OnInit, ViewChild } from "@angular/core";
@ViewChild('footerChild') footer;
run(){
this.footer.footerRun();
}
transition.module.ts
import { Component } from "@angular/core";
@Component({
selector: "app-transition",
templateUrl: "./transition.component.html",
styleUrls: ["./transition.component.scss"],
})
export class TransitionComponent {
showAside() {
//原生js获取节点
var asideDom: any = document.getElementById("aside");
asideDom.style.transform = "translate(0,0)";
}
hideAside() {
//原生js获取节点
var asideDom: any = document.getElementById("aside");
asideDom.style.transform = "translate(100%,0)";
}
}
父组件不仅可以给子组件传递简单的数据,还可把自己的方法以及整个父组件传给子组件。
<app-header [msg]="msg">app-header>
import { Component, OnInit, Input } from "@angular/core";
3.子组件中 @Input 接收父组件传过来的数据
export class HeaderComponent implements OnInit {
// Input
@Input() msg: string;
constructor() {}
ngOnInit() {}
}
<h2>这是头部组件--{{msg}}h2>
<app-footer #footerChild>app-footer>
import { Component, OnInit, ViewChild } from "@angular/core";
@ViewChild('footerChild') footer;
run(){
this.footer.footerRun();
}
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
@Output() private outer=new EventEmitter<string>();
/*用 EventEmitter 和 output 装饰器配合使用 指定类型变量*/
sendParent(){
this.outer.emit('msg from child')
}
<app-header (outer)="runParent($event)">app-header>
//接收子组件传递过来的数据
runParent(msg:string){
alert(msg);
}
Angular 中的生命周期函数
官方文档:https://www.angular.cn/guide/lifecycle-hooks
生命周期函数通俗的讲就是组件创建、组件更新、组件销毁的时候会触发的一系列的方法。
当 Angular 使用构造函数新建一个组件或指令后,就会按下面的顺序在特定时刻调用这些生命周期钩子方法。
RxJS 是 ReactiveX 库的 JavaScript 实现。它是一种强大的库,用于使用可观察对象进行异步和事件驱动编程。它提供了一种功能强大且易于使用的方式来处理异步数据流、事件序列和响应式编程。
RxJS 可以帮助开发人员轻松处理异步代码、事件和基于流的数据,同时还可以保持代码的简洁性和可读性。RxJS 的主要优点之一是它采用函数响应式编程(FRP)的方法,这意味着可以使用链式调用和组合操作来处理数据流。
RxJS 中最常用的概念是 Observable、Observer 和 Subscription。Observable 表示一个可观察对象,也就是数据源,可以发出多个值或者一个 error 或者完结信号。Observer 只是一个监听器,用于处理从 Observable 中接收的值,可以是一个回调函数或者具有 next、error、complete 方法的对象。Subscription 表示 Observable 的执行,可以取消 Observable 的执行。
除了上述概念之外,RxJS 还提供了许多操作符,用于处理 Observable 流中的数据,例如 map、filter、reduce、merge 等等。通过使用这些操作符,可以将 RxJS 的数据流转换为任何开发人员需要的形式。
RxJS 适用于各种场景,包括 Web 应用程序、移动应用程序和服务器端应用程序。通过使用 RxJS,开发人员可以轻松创建高效、可读和可维护的代码,并处理异步任务、事件和流式数据。
RXJS 的优点
异步编程:RXJS 提供了一种强大的异步编程解决方案,使得处理异步事件变得更加容易和直观。
响应式编程:RXJS 提供了一种响应式编程范式,让我们可以轻松地创建基于数据流的应用程序。
可组合性:RXJS 的操作符具有高度可组合性,可以轻松地将它们组合起来以创建复杂的数据流。
具有丰富的操作符:RXJS 拥有丰富的操作符,包括 map、filter、reduce、scan 等等,这些操作符大大简化了数据转换和过滤的过程。
RXJS 的使用场景
RXJS 在 JavaScript 中的应用非常广泛,特别是在 Web 开发中。以下是一些场景:
处理异步请求:通过使用 Observable 对象,我们可以轻松地处理异步请求,并在请求完成时获取到数据。
处理用户输入:通过创建一个数据流,我们可以监听用户输入事件,然后进行相应的处理。
处理 UI 事件:同样,我们也可以监听 DOM 事件,并根据事件的类型进行相应的操作。
处理 WebSocket 连接:使用 RXJS 可以很方便地处理 WebSocket 连接,从而实现实时通信。
总的来说,RXJS 提供了一种灵活、可组合、可扩展的异步编程解决方案,可以在许多场景下使用。
RxJS 是一个流处理库,它允许你以声明式和响应式的方式处理数据流。下面是使用 RxJS 的一些基本步骤:
npm install rxjs
import { Observable } from "rxjs";
const observable = new Observable((observer) => {
observer.next(1);
observer.next(2);
observer.next(3);
observer.complete();
});
observable.subscribe((value) => console.log(value));
observable
.pipe(map((value) => value * 2))
.subscribe((value) => console.log(value));
以上是 RxJS 的一些基本步骤。当然,RxJS 有更多的特性和操作符可供使用,具体取决于你的需求。
//1、回调函数解决异步传参问题
getCallBackData(cb: any) {
setTimeout(() => {
var data = '张三--Callback';
// return data;
cb(data);
}, 1000);
}
// callback获取异步数据
let callbackData = this.request.getCallBackData((data: any) => {
console.log("callback:" + data);
});
事件监听/发布订阅
Promise
getPromiseData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
var data = '张三--Promise';
// return data;
resolve(data);
}, 3000);
});
}
// promise获取异步数据
let promiseData = this.request.getPromiseData();
promiseData.then((data) => {
console.log(data);
});
// console.log(promiseData);
getRxjsData() {
return new Observable<any>((observer) => {
setTimeout(() => {
var data = '张三--Rxjs';
// return data;
observer.next(data);
// observer.error('失败返回这个')
}, 3000);
});
}
// Rxjs
let rxjsData = this.request.getRxjsData();
rxjsData.subscribe((data: any) => {
console.log(data);
});
从上面列子可以看到 RxJS 和 Promise 的基本用法非常类似,除了一些关键词不同。Promise 里面用的是 then()
和 resolve()
,而 RxJS 里面用的是 next()
和 subscribe()
。
从上面例子我们感觉 Promise 和 RxJS 的用法基本相似。其实Rxjs相比Promise 要强大很多
。比如 Rxjs 中可以中途撤回、Rxjs 可以发射多个值、Rxjs 提供了多种工具函数等等。
Promise 的创建之后,动作是无法撤回的。Observable 不一样,动作可以通过 unsbscribe() 方法中途撤回,而且 Observable 在内部做了智能的处理。
Promise 创建之后动作无法撤回:
let promise = new Promise((resolve) => {
setTimeout(() => {
resolve("---promise timeout---");
}, 2000);
});
promise.then((value) => console.log(value));
Rxjs 可以通过 unsubscribe() 可以撤回 subscribe 的动作:
let stream = new Observable((observer) => {
let timeout = setTimeout(() => {
clearTimeout(timeout);
observer.next("observable timeout");
}, 2000);
});
let disposable = stream.subscribe((value) => console.log(value));
setTimeout(() => {
//取消执行
disposable.unsubscribe();
}, 1000);
如果我们想让异步里面的方法多次执行,比如下面代码。
这一点 Promise 是做不到的,对于 Promise 来说,最终结果要么 resole(兑现)、要么 reject(拒绝),而且都只能触发一次。如果在同一个 Promise 对象上多次调用 resolve 方法,则会抛异常。
而 Observable 不一样,它可以不断地触发下一个值,就像 next() 这个方法的名字所暗示的那样。
//多次执行
getPromiseIntervalData() {
return new Promise((resolve, reject) => {
setInterval(() => {
var data = '张三--Promise--interval';
// return data;
resolve(data);
}, 3000);
});
}
//promise多次执行
let promiseIntervalData = this.request.getPromiseIntervalData()
promiseIntervalData.then((data)=>{//只会执行一次
console.log(data);
})
getRxjsIntervalData() {
return new Observable<any>((observer) => {
setInterval(() => {
var data = '张三--Rxjs--interval';
// return data;
observer.next(data);
// observer.error('失败返回这个')
}, 3000);
});
}
//rxjs多次执行
let rxjsIntervalData = this.request.getRxjsIntervalData()
rxjsIntervalData.subscribe((data)=>{//可以多次执行
console.log(data);
})
注意:Angular6 以后使用以前的 rxjs 方法,必须安装 rxjs-compat 模块才可以使用 map、filter 方法。
angular6 后官方使用的是 RXJS6 的新特性,所以官方给出了一个可以暂时延缓我们不需要修改 rsjx 代码的办法。
// 下载包
npm install rxjs-compat
// 引入rxjs
import {Observable} from 'rxjs';
import 'rxjs/Rx';
//使用
let stream= new Observable<any>(observer => {
let count = 0;
setInterval(() => {
observer.next(count++);
}, 1000);
});
// filter
stream.filter(val=>val%2==0).subscribe(value => console.log("filter>"+value));
// map
stream.map(value => {
return value * value
}).subscribe(value => console.log("map>"+value));
map()操作符将 Observable 发出的每个值映射
到另一个值,并将其作为新的Observable返回
。这使得您可以对 Observable 发出的值执行某些转换,例如将数字乘以 2、将字符串转换为大写字母等等。
与 map()类似,filter()也是一个操作符,用于过滤Observable发出的数据
。它基于给定的条件,只发出符合条件的值
。例如,如果我们有一个包含 1 到 10 的数字序列的 Observable,并且只想过滤出偶数,则可以使用 filter()操作符来完成。
RxJS 提供了多种延迟执行的方式。以下是其中的几种:
delay()
操作符:将 Observable 的发射事件延迟一段时间后再发出。例如,of(1, 2, 3).pipe(delay(1000)) 会在 1 秒后依次发出 1、2、3 这三个值。timer()
操作符:在指定时间后发出一个值,可以配合其他操作符使用。例如,timer(1000).pipe(map(() => ‘hello’)) 会在 1 秒后发出字符串 ‘hello’。debounceTime()
和 throttleTime() 操作符:分别用于防抖和节流。debounceTime() 会在 Observable 发射值后等待一段时间,然后才发出这个值。如果在等待期间又有新的值发射,就会重新开始计时。throttleTime() 则是在一段时间内只发出第一个值,忽略后续的值,直到时间到了才允许下一个值通过。delayWhen()
操作符:将 Observable 的发射事件延迟一段时间后再发出,但是这段时间是由一个 Observable 决定的。例如,of(1, 2, 3).pipe(delayWhen(() => timer(1000))) 会在 1 秒后依次发出 1、2、3 这三个值。除了上述操作符外,还有 timeout()
、delayWhen()
等操作符也可以实现延迟执行。在使用时需要根据实际需求选择合适的操作符。
import { Observable, fromEvent } from "rxjs";
import { map, filter, throttleTime } from "rxjs/operators";
var button = document.querySelector("button");
fromEvent(button, "click")
.pipe(throttleTime(1000))
.subscribe(() => console.log(`Clicked`));
1、在 app.module.ts 中引入 HttpClientModule 并注入
import { HttpClientModule } from "@angular/common/http";
imports: [BrowserModule, HttpClientModule];
2、在用到的地方引入 HttpClient 并在构造函数声明
import { HttpClient } from "@angular/common/http";
constructor(public http:HttpClient) { }
3、get 请求数据
var api = "http://a.itying.com/api/productlist";
this.http.get(api).subscribe((response) => {
console.log(response);
});
Angular5.x 以后 get、post 和和服务器交互使用的是 HttpClientModule 模块。
1、在 app.module.ts 中引入 HttpClientModule 并注入
import { HttpClientModule } from "@angular/common/http";
imports: [BrowserModule, HttpClientModule];
2、在用到的地方引入 HttpClient 、HttpHeaders 并在构造函数声明 HttpClient
import { HttpClient, HttpHeaders } from "@angular/common/http";
constructor(public http:HttpClient) { }
3、post 提交数据
const httpOptions = {
headers: new HttpHeaders({ "Content-Type": "application/json" }),
};
var api = "http://127.0.0.1:3000/doLogin";
this.http
.post(api, { username: "张三", age: "20" }, httpOptions)
.subscribe((response) => {
console.log(response);
});
1、在 app.module.ts 中引入 HttpClientModule、HttpClientJsonpModule 并注入
import { HttpClientModule, HttpClientJsonpModule } from "@angular/common/http";
imports: [BrowserModule, HttpClientModule, HttpClientJsonpModule];
2、在用到的地方引入 HttpClient 并在构造函数声明
import { HttpClient } from "@angular/common/http";
constructor(public http:HttpClient) { }
3、jsonp 请求数据
var api = "http://a.itying.com/api/productlist";
this.http.jsonp(api, "callback").subscribe((response) => {
console.log(response);
});
1、安装 axios
npm install axios --save
2、用到的地方引入 axios
import axios from "axios";
3、看文档使用
axios
.get("/user?ID=12345")
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
});
Angular 中的路由可以用来实现不同组件之间的导航。它允许用户在应用程序中导航到不同的页面或视图,而无需刷新整个页面。
以下是如何使用路由在 Angular 中进行导航的步骤:
您需要安装@angular/router 模块,这可以通过 npm 包管理器来完成。在终端窗口中运行以下命令:
npm install @angular/router --save
打开 app.module.ts 文件,并导入 RouterModule 和 Routes:
import { RouterModule, Routes } from "@angular/router";
一般,我们在新建一个 angular 项目时,会选择是否添加路由,如果输入 y 即可自动帮我们引入第二步的包,所以通常 1、2 步可以省略
在 app-routing.module.ts(创建项目时选择创建路由时自动生成该文件)(app.module.ts)中,创建一个路由数组,它将定义您的应用程序中的所有路由。示例如下:
const routes: Routes = [
{ path: "", component: HomeComponent },
{ path: "about", component: AboutComponent },
{ path: "contact", component: ContactComponent },
{ path: "**", redirectTo: "" }, //找不到页面时就重定向
];
在这个例子中,我们定义了三个路由:首页(/),关于页面(/about)和联系页面(/contact)。
在 app-routing.module.ts(app.module.ts)的 NgModule 元数据中,将路由添加到 imports 数组中:
@NgModule({
declarations: [AppComponent, HomeComponent, AboutComponent, ContactComponent],
imports: [BrowserModule, RouterModule.forRoot(routes)],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
这一步通常也可以省略,创建项目时已经生成了
在 AppComponent 模板中添加一个 router-outlet 标签,这将成为您的应用程序中所有组件的路由容器:
<router-outlet>router-outlet>
在应用程序的任何组件中,都可以使用 routerLink 指令创建导航链接。例如,在菜单组件中,您可以创建以下链接:
<a routerLink="/">Homea>
<a routerLink="/about">Abouta>
<a routerLink="/contact">Contacta>
当用户单击其中一个导航链接时,Angular 会自动导航到相应的路由。如果您要通过编程方式进行导航,可以注入 Router 服务并使用 navigate()方法来实现:
import { Router } from '@angular/router';
constructor(private router: Router) {}
goToAboutPage() {
this.router.navigate(['/about']);
}
这就是如何在 Angular 中使用路由进行导航的基本步骤。
1.配置动态路由
const routes: Routes = [
{ path: "home", component: HomeComponent },
{ path: "news", component: NewsComponent },
// /:id 接收动态参数
{ path: "newscontent/:id", component: NewscontentComponent },
{
path: "",
redirectTo: "/home",
pathMatch: "full",
},
];
2.跳转传值(理不明白的话看视频更好理解)
<a [routerLink]="[ '/newscontent/',aid]">跳转到详情</a>
<a [routerLink]="/newscontent/{{aid}}">跳转到详情</a>
3.获取动态路由的值
import { ActivatedRoute } from "@angular/router";
constructor( private route: ActivatedRoute) {
}
ngOnInit() {
console.log(this.route.params);
this.route.params.subscribe(data=>this.id=data.id);
}
import { Router } from "@angular/router";
2.初始化
export class HomeComponent implements OnInit {
constructor(private router: Router) {}
ngOnInit() {}
goNews() {
// this.router.navigate(['/news', hero.id]);
this.router.navigate(["/news"]);
}
}
3.路由跳转
this.router.navigate(["/news", hero.id]);
import { Router, NavigationExtras } from "@angular/router";
goNewsContent(){
let navigationExtras: NavigationExtras = {
queryParams: { 'session_id': '123' },
fragment: 'anchor'
};
this.router.navigate(['/news'],navigationExtras);
}
constructor(private route: ActivatedRoute) {
console.log(this.route.queryParams);
}
import { NewsaddComponent } from "./components/newsadd/newsadd.component";
import { NewslistComponent } from "./components/newslist/newslist.component";
{
path: 'news',
component:NewsComponent,
children: [
{
path:'newslist',
component:NewslistComponent
},
{
path:'newsadd',
component:NewsaddComponent
}]}
<router-outlet></router-outlet>
// js跳转路由
/*
---------动态路由----------
1.引入声明模块
import { Router } from '@angular/router';
constructor(public router:Router){}
2.跳转
this.router.navigate(['/productcontent', '1234'])
//跳转并进行get传值
let queryParams:NavigationExtras = {
queryParams:{aid:111}
}
this.router.navigate(['/news'],queryParams)
-----------get传值-----------
1.引入声明模块
import { Router,NavigationExtras } from '@angular/router';
constructor(public router:Router){}
2.跳转
//跳转并进行get传值
let queryParams:NavigationExtras = {
queryParams:{aid:111}
}
Angular 是一个 JavaScript 框架,它的核心模块包括:
@angular/core
:这是最重要的模块之一,它定义了 Angular 应用程序所需的各种核心组件和服务。
包括:Component、Directive、Pipe、Service 等。
@angular/common
:这个模块提供了许多通用的 Angular 功能,例如日期格式化、数字格式化、国际化支持等。
包括:CommonModule、NgIf、NgForOf、DecimalPipe 等。
另外,Angular 还有其他几个常用的模块:
@angular/forms
:这个模块提供了表单构建、验证、交互等功能。
包括:FormsModule、ReactiveFormsModule、FormControl 等。
@angular/platform-browser
:这个模块允许你在浏览器中运行 Angular 应用程序,并为其提供了 DOM、HTTP 等基本功能。
包括:BrowserModule、platformBrowserDynamic、HttpClient 等。
通过引入这些模块可以让我们更方便地开发 Angular 应用程序。
当我们项目比较小的时候可以不用自定义模块。但是当我们项目非常庞大的时候把所有的组件都挂载到根模块里面不是特别合适。所以这个时候我们就可以自定义模块来组织我们的项目。并且通过 Angular 自定义模块可以实现路由的懒加载。
// 新建模块
ng g module module/user
// 模块中新建组件
ng g component module/user //这一步执行完后就会和app的内容差不多
ng g component module/user --routing //还可以加上路由
ng g component module/user/components/profile
//模块中新建服务
ng g service module/user/services/common
// 引入自定义模块
import { UserModule } from './modules/user/user.module';
...
imports: [
...
UserModule,
...
],
<h2>调用用户模块h2>
<app-user>app-user>
这里一般我们只能调用到自定义模块的根组件,如果想要在外部调用自定义模块的子组件,比如 ProfileComponent,就需要在自定义模块(user.module.ts)中导出
exports:[UserComponent, ProfileComponent],//暴露组件,让其他模块里面可以使用暴露的组件
懒加载—并没有引入相应组件,而是通过路由去跳转到相应界面
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, AppRoutingModule],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule {}
<header>
<a [routerLink]="[ '/user' ]">用户模块a>
<a [routerLink]="[ '/product' ]">产品模块a>
<a [routerLink]="[ '/article' ]">文章模块a>
header>
<router-outlet>router-outlet>
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
// 懒加载---并没有引入相应组件,而是通过路由去跳转到相应界面
const routes: Routes = [
{
path: "user",
loadChildren: () =>
import("./module/user/user.module").then((x) => x.UserModule),
},
{
path: "product",
loadChildren: () =>
import("./module/product/product.module").then((x) => x.ProductModule),
},
{
path: "article",
loadChildren: () =>
import("./module/article/article.module").then((x) => x.ArticleModule),
},
{ path: "**", redirectTo: "user" },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { ProfileComponent } from "./components/profile/profile.component";
import { AddressComponent } from "./components/address/address.component";
import { UserComponent } from "./user.component";
//第一个path!!!
const routes: Routes = [
{ path: "", component: UserComponent },
{ path: "profile", component: ProfileComponent },
{ path: "address", component: AddressComponent },
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class UserRoutingModule {}