Angular 从零开始,快速上手
- [一、AngularJS 简介](#一、AngularJS 简介)
-
- [1.1 AngularJS 的背景](#1.1 AngularJS 的背景)
- [1.2 AngularJS 的简介](#1.2 AngularJS 的简介)
- [1.3 AngularJS 概念概述](#1.3 AngularJS 概念概述)
- [1.4 AngularJS 特性](#1.4 AngularJS 特性)
- [1.5 AngularJS 和 JQuery 比较](#1.5 AngularJS 和 JQuery 比较)
- [二、安装 AngularJS](#二、安装 AngularJS)
-
- [2.1 方式一:使用在线 cdn](#2.1 方式一:使用在线 cdn)
- [2.2 方式二:使用依赖管理工具 npm](#2.2 方式二:使用依赖管理工具 npm)
- [三、AngularJS 的生命周期](#三、AngularJS 的生命周期)
-
- [3.1 使用步骤](#3.1 使用步骤)
- [3.2 生命周期钩子函数](#3.2 生命周期钩子函数)
- [四、Angular 的基础语法](#四、Angular 的基础语法)
-
- [3.1 模块和组件](#3.1 模块和组件)
-
- [3.1.1 使用命令创建模块](#3.1.1 使用命令创建模块)
- [3.1.2 使用命令创建组件](#3.1.2 使用命令创建组件)
- [3.2 指令](#3.2 指令)
-
- [3.2.1 AnguarJS 指令](#3.2.1 AnguarJS 指令)
- [3.2.2 数据绑定](#3.2.2 数据绑定)
- [3.2.3 判断指令](#3.2.3 判断指令)
- [3.2.4 循环指令](#3.2.4 循环指令)
- [3.2.5 事件处理](#3.2.5 事件处理)
- [3.2.6 自定义指令](#3.2.6 自定义指令)
- [3.3 组件交互](#3.3 组件交互)
-
- [3.3.1 父组件->子组件](#3.3.1 父组件->子组件)
- [3.3.2 子组件->父组件](#3.3.2 子组件->父组件)
- [3.4 控制器](#3.4 控制器)
-
- [3.4.1 控制器](#3.4.1 控制器)
- [3.4.2 组件](#3.4.2 组件)
- [3.5 装饰器(注解)](#3.5 装饰器(注解))
-
- [3.5.1 `@Component`](#3.5.1
@Component
) - [3.5.2 `@Directive`](#3.5.2
@Directive
) - [3.5.3 `@Injectable`](#3.5.3
@Injectable
) - [3.5.4 `@Pipe`](#3.5.4
@Pipe
)
- [3.5.1 `@Component`](#3.5.1
- [3.6 服务](#3.6 服务)
-
- [3.6.1 创建服务](#3.6.1 创建服务)
- [3.6.2 注入服务](#3.6.2 注入服务)
- [3.6.3 提供服务](#3.6.3 提供服务)
- [3.7 管道](#3.7 管道)
-
- [3.7.1 常用的内置管道函数](#3.7.1 常用的内置管道函数)
- [3.7.2 自定义管道](#3.7.2 自定义管道)
- [3.8 HttpClient](#3.8 HttpClient)
- [3.9 路由](#3.9 路由)
- 五、总结
一、AngularJS 简介
1.1 AngularJS 的背景
AngularJS
诞生于2009年,由 Misko Hevery 等人创建,后为Google
所收购。是一款由Google
开发优秀的前端JS框架,于2010年首次发,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。
AngularJS
的核心思想是使用MVC(Model-View-Controller
)架构模式来构建Web应用程序。
在 AngularJS
出现之前,Web开发中存在许多挑战。传统的 JavaScript 开发方式需要手动管理DOM元素、处理事件、实现数据绑定等,这使得代码复杂、难以维护,并且在大型应用程序中容易出现问题。此外,前端开发和后端开发之间的协作也不够紧密,导致开发过程中出现了许多矛盾和冲突。
AngularJS
的出现改变了这种情况。它引入了许多新概念和技术,以提供更高效、更一致的开发体验。总之,AngularJS的背景可以追溯到对传统前端开发模式的不满和对更好的开发体验的追求。它引入了许多创新的概念和技术,帮助开发者构建更高效、可维护的Web应用程序。
AngularJS官网:https://angularjs.org/
AngularJS中文网:https://www.angularjs.net.cn/
小知识
AngularJS
是由 Google 开发的一款前端框架,而 Angular 是其后续版本的重写和升级。以下是它们之间的一些主要区别:
- 语言: AngularJS 使用 JavaScript,而Angular使用TypeScript。TypeScript是JavaScript的超集,为开发大型应用提供了更强大的工具和类型检查。
- 模块化: AngularJS没有原生支持模块化开发,而Angular使用模块化的方式来组织代码。Angular中的模块提供了更好的可维护性和可扩展性。
- 指令: 在AngularJS中,指令比较灵活且是核心概念之一。而在Angular中,很多原本内置的指令被废弃或者重新实现。
- 性能: Angular相对于AngularJS有更好的性能表现,这部分得益于对变化检测和渲染管道的改进。
- 移动端支持: Angular为移动端开发提供了更好的支持,并且引入了一些移动端特有的功能。
- 依赖注入: Angular的依赖注入系统进行了调整和优化,更易于理解和使用。
总体来说,Angular
是对AngularJS
的全面改进和升级,提供了更现代化、高性能、易维护的前端开发体验。
从 2016 年开始,AngularJS
开始被称为 Angular
。这是因为 Angular
团队在这个时候发布了 Angular 2
,这是对 AngularJS 的全面重写和升级。为了避免混淆,AngularJS 框架通常被称为 Angular 1
,而新的版本则简称为 Angular。
1.2 AngularJS 的简介
AngularJS
是一个开发动态 Web 应用的 JS 框架。它是为了扩展 HTML 在构建应用时本应具备的能力而设计的。
Angular通过指令(directive
)扩展HTML的语法。例如:
- 通过
{``{}}
进行数据绑定。 - 使用DOM控制结构来进行迭代或隐藏DOM片段。
- 支持表单和表单验证。
- 将逻辑代码关联到DOM元素上。
- 将一组HTML做成可重用的组件。
1.3 AngularJS 概念概述
概念 | 说明 |
---|---|
模板(Template) | 带有Angular扩展标记的HTML |
指令(Directive) | 用于通过自定义属性 和元素扩展HTML的行为 |
模型(Model) | 用于显示给用户并且与用户互动的数据 |
作用域(Scope) | 用来存储模型(Model)的语境(context)。模型放在这个语境中才能被控制器、指令和表达式等访问到 |
表达式( Expression) | 模板中可以通过它来访问作用域(Scope)中的变量和函数 |
编译器(Compiler) | 用于编译 模板(Template),并且对其中包含的指令(Directive)和表达式(Expression)进行实例化 |
过滤器(Filter) | 负责格式化表达式(Expression)的值,以便呈现给用户 |
视图(View) | 用户看到的内容(即DOM) |
数据绑定(Data Binding) | 自动同步模型(Model)中的数据和视图(View)表现 |
控制器(Controller) | 视图(View)背后的业务逻辑 |
依赖注入(Dependency Injection) | 负责创建和自动装配对象或函数 |
注入器(Injector) | 用来实现依赖注入(Injection)的容器 |
模块(Module) | 用来配置注入器 |
服务(Service) | 独立于视图(View)的、可复用的业务逻辑 |
1.4 AngularJS 特性
- 双向数据绑定:AngularJS引入了双向数据绑定的概念,使得数据模型和视图之间保持同步。当数据模型发生变化时,视图会自动更新,反之亦然。这简化了数据管理和界面更新的过程。
- MVVM架构 :AngularJS采用了MVVM(
Model-View-ViewModel
)架构模式,将应用程序分为模型、视图和视图模型三个部分。视图模型负责处理视图的逻辑和状态,将数据从模型传递给视图,并监听视图中的变化。 - 模块化设计:AngularJS支持将应用程序拆分为多个模块,每个模块负责特定的功能。模块化的设计使得代码更易于组织、测试和维护,并促进了团队协作。
- 强大的模板系统:AngularJS使用基于HTML的模板系统,使开发者能够以声明式的方式定义应用程序的视图。模板中可以包含AngularJS的指令、表达式和过滤器,以及自定义的HTML标签和属性。
- 强大的指令系统:AngularJS的指令系统允许开发者创建自定义的指令,扩展HTML的功能。指令可以用于操作DOM元素、处理事件、实现数据绑定等,从而使开发更加灵活和高效。
- 依赖注入:AngularJS使用依赖注入的概念来管理组件之间的依赖关系。通过依赖注入,开发者可以声明一个组件所依赖的其他组件或服务,并由框架负责解析和注入这些依赖。这种解耦的方式使得代码更具可测试性、可维护性,并且促进了模块化和复用。
- 测试友好:AngularJS提供了丰富的测试工具和框架,使得开发者可以轻松地编写单元测试、集成测试和端到端测试来确保应用程序的质量和稳定性性
1.5 AngularJS 和 JQuery 比较
实现效果:
-
JQuery
html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名:<input id="username" type="text"> <br> 你输入的内容是:<span id="content"></span> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <script> $(function () { $('#username').keyup(function () { var value = $(this).val(); $('#content').html(value) }) }) </script> </body> </html>
-
AngularJS
html<!DOCTYPE html> <html lang="en" ng-app> <head> <meta charset="UTF-8"> </head> <body> 用户名:<input id="username" ng-model="username" type="text"> <br> 你输入的内容是:<span id="content">{{username}}</span> <script src="http://code.angularjs.org/1.2.25/angular.min.js"></script> </body> </html>
Angular提供了动态 (
live
)的绑定: 当input
元素的值变化的时候,表达式的值也会自动重新计算,并且DOM所呈现的内容也会随着这些值的变化而自动更新。 这种模型(model
)与视图(view
)的联动就叫做"双向数据绑定"。
二、安装 AngularJS
2.1 方式一:使用在线 cdn
html
<!-- 1. 引入在线地址 -->
<script src="http://code.angularjs.org/1.2.25/angular.min.js"></script>
<!-- 2. 下载到本地,引入文件 -->
<script src="../js/angular.js"></script>
2.2 方式二:使用依赖管理工具 npm
-
安装 nodejs
-
安装angular
powershell# 默认下载最新版本 npm i -g @angular/cli # 下载指定版本 16.0.3 npm i -g @angular/cli@16.0.3
-
创建项目
powershellng new 项目名
-
文件结构
powershelle2e:测试目录 src: { index.html:网站主页面 main.ts:应用主入口 } src-app: //模块和组件 { app.component.css //模块/组件的css样式 app.component.html //模块/组件的html页面 app.component.ts //模块/组件的程序文件 } src-assets: 存放静态资源文件 src-environments :环境配置 src-favicon.ico 图标 src-index.html 整个应用的根html main.ts 整个web应用的入口点,脚本执行的入口点 polyfills.ts导入一些必要的库 styless.css全局样式文件 angular-cli.json 命令行工具的配置文件, karma ,protractor.conf.js 单元测试的追踪器 package.json npm配置文件,列明了当前应用所使用的依赖包 tslint.json tslint的配置文件
-
运行
powershellng serve --open 或者npm start
三、AngularJS 的生命周期
3.1 使用步骤
javascript
// 1. 要使用哪个钩子函数,就先引入
import { OnInit } from ...
// 2. 再实现
export class 组件名 implements Onint...
// 3. 再使用
ngOnInit(){
....
}
3.2 生命周期钩子函数
-
ngOnChanges()
- 当输入属性的值发生变化时调用。
- 在组件被创建并且输入属性绑定发生变化时调用。首次调用一定会发生在
ngOnInit()
之前。
-
ngOnInit()
- 在组件初始化时调用。
- 通常用于执行初始化逻辑,例如获取初始数据。在第一轮
ngOnchanges()
完成之后调用,只调用一次。
-
ngDoCheck()
- 当 Angular 安排检查时调用。
- 用于自定义的变更检测逻辑,通常与 ChangeDetectorRef 结合使用。在
ngOnChanges()
和ngOnInit()
之后。
-
ngAfterContentInit()
- 在组件内容投影完成后调用。
- 用于执行需要在组件内容初始化后执行的逻辑。第一次
ngDoCheck()
之后调用,只调用一次,只适用于组件。
-
ngAfterContentChecked()
- 在每次 Angular 完成对组件内容的检查之后调用。
- 用于执行在内容检查之后需要执行的逻辑。
ngAfterContentInit()
和每次ngDoCheck()
之后调用,只适用于组件。
-
ngAfterViewInit()
- 在组件视图初始化完成后调用。
- 用于执行需要访问视图的初始化逻辑。第一次
ngAfterContentChecked()
之后调用,只调用一次,只适合组件。
-
ngAfterViewChecked()
- 在每次 Angular 完成对组件视图的检查之后调用。
- 用于执行在视图检查之后需要执行的逻辑。
ngAfterViewInit()
和每次ngAfterContentChecked()
之后调用,只适合组件。
-
ngOnDestroy()
- 在组件销毁时调用。
- 通常用于清理资源,取消订阅等。
四、Angular 的基础语法
3.1 模块和组件
项目根模块 :app.module.ts
定义的组件都需要在app.module.ts
文件里先进行 import 引入,然后再@NgModule({deckartions:[]})
声明
- 定义组件模板的两种方式 :
- 使用
templateurl
引用一个html
文件 - 使用
template + es6
的模板字符串
- 使用
- 定义组件样式的两种方式 :
- 使用
styleUrls
引入一个css
文件 - 使用
style + es6
的模板字符串
- 使用
- 元数据:通过装饰器描述组件
3.1.1 使用命令创建模块
-
生成模块
htmlng g module customers --routing=true # customers 为模块名称, --routing=true 是否包含路由
-
文件解析
生成的模块文件有个路由文件(
customers-routing.modules.ts
)和(customers.modules.ts
)
-
在项目的根路由文件引入模块
vueconst routes: Routes = [ { path: '', pathMatch: 'full', redirectTo: 'CustomersModule' }, //重定向 { path: 'CustomersModule',loadChildren:()=>import('./customers/customers.module').then(m=>m.CustomersModule)} ];
3.1.2 使用命令创建组件
-
生成组件
先打开需要创建组件的模块,然后进入到模块命令行中,使用命令
powershellng generate component 组件名 # (组件名只能小写,不能大写)或者缩写ng g c 组件 # 创建 hello 组件 ng g c hello
-
文件解析
会生成一个hello的文件夹,里面有几个文件,我们可以在
hello.component.html
写一段文字<p>我是第一个组件</p>
-
引入组件
在模块的路由文件里引入组件
vueimport { HelloComponent } from './hello/hello.component'; const routes: Routes = [ {path:"hello",component:HelloComponent} ];
然后保存,等编译器重新编译之后,输入刚才的模块的路由,就可以显示出来了
vuehttp://localhost:4200/CustomersModule //url地址/模块名称 http://localhost:4200/CustomersModule/hello //url地址/模块名称/模块里的组件
-
效果
3.2 指令
AngularJS
通过被称为 指令 的新属性来扩展 HTML
AngularJS 通过内置的指令来为应用添加功能
AngularJS 允许你自定义指令
3.2.1 AnguarJS 指令
AngularJS
指令是扩展的 HTML 属性,带有前缀 ng- 。
ng-app 指令初始化一个 AngularJS 应用程序。
ng-init 指令初始化应用程序数据。
ng-model 指令把元素值(比如输入域的值)绑定到应用程序。
html
<!-- AngularJS -->
<div ng-app="" ng-init="firstName='John'">
<p>在输入框中尝试输入:</p>
<p>姓名:<input type="text" ng-model="firstName"></p>
<p>你输入的为: {{ firstName }}</p>
</div>
<!-- Angular -->
<!-- html -->
<div>
<p>在输入框中尝试输入:</p>
<p>姓名:<input type="text" [(ngModel)]="firstName"></p>
<p>你输入的为: {{ firstName }}</p>
</div>
<!-- ts -->
export class ParentComponent {
firstName: string = 'John Doe';
}
ng-app 指令告诉 AngularJS,
元素是 AngularJS 应用程序 的"所有者"。
3.2.2 数据绑定
上面实例中的 {{ firstName }} 表达式是一个 AngularJS 数据绑定表达式。AngularJS 中的数据绑定,同步了 AngularJS 表达式与 AngularJS 数据。{{ firstName }} 是通过 ng-model="firstName" 进行同步。
在下一个实例中,两个文本域是通过两个 ng-model 指令同步的:
html
<!-- AngularJS -->
<div ng-app="" ng-init="quantity=1;price=5">
<h2>价格计算器</h2>
数量: <input type="number" ng-model="quantity">
价格: <input type="number" ng-model="price">
<p><b>总价:</b> {{ quantity * price }}</p>
</div>
<!-- Angular -->
<div>
<h2>价格计算器</h2>
数量: <input type="number" [(ngModel)]="quantity">
价格: <input type="number" [(ngModel)]="price">
<p><b>总价:</b> {{ quantity * price }}</p>
</div>
<!-- ts -->
export class ParentComponent {
quantity: number = 1;
price: number = 5;
}
3.2.3 判断指令
-
ngIf
html<!-- 如果isAvailable为true,那么段落元素会被渲染出来;如果isAvailable为false,它将被移除。 --> <!-- AngularJS --> <p ng-if="isAbailable">该商品现在可供购买。</p> <!-- Angular --> <p *ngIf="isAbailable">该商品现在可供购买。</p>
ng-show和ng-hide指令也可以根据条件来显示或隐藏元素,但是它们实际上是通过控制元素的display属性来实现的,而不是真正地移除元素。
html<p ng-show="isVisible">这个元素会根据isVisible的值进行显示/隐藏。</p> <p ng-hide="isHidden">这个元素会根据isHidden的值进行显示/隐藏。</p>
-
ngSwitch
根据color的值,会显示不同的段落内容。如果color为'red',则显示"红色";如果color为'blue',则显示"蓝色";否则,显示"其他颜色"。
html<!-- AngularJS --> <div ng-switch on="color"> <p ng-switch-when="'red'">红色</p> <p ng-switch-when="'green'">绿色</p> <p ng-switch-when="'blue'">蓝色</p> <p ng-switch-default>其他颜色</p> </div> <!-- Angular --> <div [ngSwitch]="color"> <p *ngSwitchCase="'red'">红色</p> <p *ngSwitchCase="'green'">绿色</p> <p *ngSwitchCase="'blue'">蓝色</p> <p *ngSwitchDefault>其他颜色</p> </div>
-
*
和[]
的区别在
Angular
中,*
号是结构型指令的标志,用于表示对DOM结构进行操作。而[...]
则是属性型指令的标志,用于修改HTML元素的属性。因此,
ngSwitch
实际上是一个语法糖,它是Angular为了简化代码书写所提供的一种便利方式。当我们使用*ngSwitch
时,Angular实际上会将其转换为[ngSwitch]
,这是因为ngSwitch是一个属性型指令,用于控制元素的属性,而不是直接控制DOM结构。
3.2.4 循环指令
该指令可以用来遍历集合中的每个项,并为每个项生成相应的 DOM 元素。
html
<!-- AngularJS,只能使用in来遍历对象的属性 -->
<ul>
<li ng-repeat="item in items">{{ item.name }}</li>
</ul>
<!-- Augular, 既可以用in来遍历又可以使用of来遍历,let用来接受局部变量 -->
<ul>
<li *ngFor="let item of items">{{ item.name }}</li>
</ul>
of 和 in 的区别:'in'用于遍历对象属性,而'of'用于遍历数组或可迭代对象的元素
3.2.5 事件处理
-
ng-click
用于处理元素的点击事件
html<!-- AngularJS --> <button ng-click="doSomething()">点击我</button> <!-- 在控制器中通过$scope绑定事件处理函数 --> $scope.doSomething = function() { // 处理点击事件的逻辑 } <!-- Angular --> <button (click)="doSomething()">点击我</button> <!-- 组件类方法, 在组件类中定义方法来处理事件,然后在模板中进行调用 --> export class MyComponent { doSomething() { // 处理点击事件的逻辑 } handleInputChange(event: any) { // 处理输入框改变事件的逻辑 } submitForm() { // 处理表单提交事件的逻辑 } }
-
ng-change
用于处理输入框内容改变时的事件
html<!-- AngularJS --> <input type="text" ng-model="inputValue" ng-change="handleInputChange()"> <!-- Angular --> <input type="text" (change)="handleInputChange($event)">
-
ng-submit
用于处理表单提交事件
html<!-- AngularJS --> <form ng-submit="submitForm()"> <input type="text" ng-model="formData.username"> <button type="submit">提交</button> </form> <!-- Angular --> <form (ngSubmit)="submitForm()"> <input type="text" [(ngModel)]="formData.username"> <button type="submit">提交</button> </form>
-
其他事件指令
html鼠标悬停事件: ng-mouseover / (mouseover) 鼠标移出事件: ng-mouseout / (mouseout) 输入框获得焦点时: ng-focus / (focus)
3.2.6 自定义指令
-
创建自定义指令
使用命令
ng generate directive 指令名
或者在文件夹(module下)中创建一个以.directive.ts
结尾的文件。 -
实现自定义指令
在生成的
custom-directive.directive.ts
文件中,你可以实现自定义指令typescriptimport { Directive, ElementRef } from '@angular/core' @Directive({ selector: '[appCustomDirective]' }) export class appCustomDirective { constructor(private elementRef: ElementRef) { this.elementRef.nativeElement.style.backgroundColor = 'yellow' } }
-
在模块中声明和导入
在你的 Angular 模块中,确保将自定义指令声明并导入:
typescriptimport { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { appCustomDirective } from './custom-directive.directive'; @NgModule({ declarations: [ appCustomDirective, // 其他组件、指令等 ], imports: [BrowserModule], bootstrap: [/* 主应用组件 */] }) export class AppModule { }
-
在模板中使用
html<div appCustomDirective> This is a div with a custom directive. </div>
装饰器
@Directive
装饰器是Angular框架中用来创建自定义指令的装饰器之一。装饰器是一种特殊类型的声明,它可以附加到类、方法、属性或参数上,以提供额外的元数据和行为。
在Angular中,@Directive
装饰器用于标记一个类作为自定义指令,并提供该指令的配置信息。通常情况下,@Directive
装饰器会包含一个对象作为参数,该对象用于描述指令的各种属性,如选择器、输入输出属性、链接函数等。
3.3 组件交互
在Angular中,组件之间的交互可以通过多种方式来实现,包括输入属性、服务的使用、事件广播等。
3.3.1 父组件->子组件
-
输入属性 (
@Input
)父组件可以把数据通过属性绑定的方式传递给子组件。
javascript// 通过输入属性将父组件的 message 传递给子组件 @Component({ selector: 'app-child', template: '{{ message }}' }) export class ChildComponent { // 子组件接收,@Input() 只能取值,不能监听值的变化 @Input() message: string; } @Component({ selector: 'app-parent', template: '<app-child [message]="parentMessage"></app-child>' }) export class ParentComponent { parentMessage = 'Hello World'; }
-
服务 (
Service
)服务是一种可注入的类,用于共享数据和功能。通过在提供商列表中注册服务,多个组件可以共享该服务实例并相互通信。
javascript@Injectable({ providedIn: 'root' }) export class DataService { data: string; setData(data: string) { this.data = data; } getData() { return this.data; } } @Component({ selector: 'app-child', template: '{{ data }}' }) export class ChildComponent { data: string; constructor(private dataService: DataService) {} ngOnInit() { this.data = this.dataService.getData(); } } @Component({ selector: 'app-parent', template: '<app-child></app-child>' }) export class ParentComponent { constructor(private dataService: DataService) {} ngOnInit() { this.dataService.setData('Hello World'); } }
-
事件广播
父组件可以通过
broadcast
或emit
广播事件,然后子组件可以通过scope.on
来监听事件并获取数据。javascriptapp.controller('parentController', ['$scope', function($scope) { $scope.$broadcast('dataEvent', 'Data from parent'); }]); app.controller('childController', ['$scope', function($scope) { $scope.$on('dataEvent', function(event, data) { // 使用data来访问父组件传递的数据 }); }]);
-
模板引用变量
使用模板引用变量,一个组件可以获取到另一个组件或 HTML 元素的引用,并直接操作其属性和方法。模板引用变量可以通过在HTML标签中使用#号来声明,并且可以在模板中的任何地方使用。
javascript// html 其中#nameInput就是一个模板变量,它引用了input元素 <form> <label for="name">Name:</label> <input #nameInput id="name" type="text"> <button (click)="submitForm()">Submit</button> </form> // js @Component({ selector: 'app-form', template: './form.component.html' }) export class FormComponent { @ViewChild('nameInput') nameInput: ElementRef<HTMLInputElement>; submitForm() { // 聚焦到 input 元素 this.nameInput.nativeElement.focus(); } }
除了用在普通的HTML元素上,模板引用变量也可以用在组件上,以获取对组件实例的引用。
html<app-child #childComponent></app-child> <!-- #childComponent引用了子组件实例,然后在父组件中可以直接调用子组件的方法。 --> <button (click)="childComponent.doSomething()">Call Child Component Method</button>
3.3.2 子组件->父组件
-
输出属性(
**@Output**
)javascript@Component({ selector: 'app-child', template: '<button (click)="sendMessage()">Send Message</button>' }) export class ChildComponent { @Output() messageEvent = new EventEmitter<string>(); sendMessage() { this.messageEvent.emit('Hello from child'); } } @Component({ selector: 'app-parent', template: '<app-child (messageEvent)="receiveMessage($event)"></app-child>{{ message }}' }) export class ParentComponent { message: string; receiveMessage(message: string) { this.message = message; } }
-
服 务(
Service
)与父组件到子组件一样
-
事件广播
与父组件到子组件一样
-
模板引用变量
与父组件到子组件一样
3.4 控制器
3.4.1 控制器
控制器是AngularJS中的一个重要概念,用于处理业务逻辑和管理数据。通过控制器,你可以将数据模型添加到作用域(Scope)中,并定义处理数据的函数。
typescript
app.controller('myCtrl', function($scope) {
$scope.name = "John Doe";
});
在上述示例中,我们创建了一个名为myCtrl的控制器,并将name变量添加到作用域中。在HTML中,我们可以使用ng-controller指令将控制器与特定的HTML元素关联起来。
html
<div ng-controller="myCtrl">
<p>Hello, {{ name }}!</p>
</div>
ng-controller
指令定义了应用程序控制器。控制器是JavaScript 对象,由标准的 JavaScript 对象的构造函数 创建。AngularJS 使用$scope
对象来调用控制器。在 AngularJS 中, $scope
是一个应用对象(属于应用变量和函数)。
控制器的 $scope
(相当于作用域、控制范围)用来保存AngularJS Model(模型)的对象。控制器在作用域中创建了一个属性 (name),然后使用条件表达式{``{ name }}
使用。
3.4.2 组件
在 Angular 中,控制器的概念被组件(Component
)所取代。组件是 Angular 应用中的基本构建块,负责管理视图和业务逻辑。
组件:在 Angular 中,组件是一种带模板的指令,它包含了与视图相关联的数据和行为逻辑。每个组件都有自己的模板、样式和行为,它们可以嵌套使用,形成应用程序的整体结构。
-
定义组件类
typescriptimport { Component } from '@angular/core'; @Component({ selector: 'my-component', template: `<h1>{{ title }}</h1>`, }) export class MyComponent { title = 'Hello, World!'; }
上面的代码定义了一个名为 MyComponent 的组件,它包含了一个属性 title 和一个模板,模板中显示了 title 的值。
-
引入到模块中
typescriptimport { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { MyComponent } from './my.component'; @NgModule({ imports: [BrowserModule], declarations: [MyComponent], bootstrap: [MyComponent] }) export class MyAppModule {}
这段代码将 MyComponent 引入到模块中,并声明为该模块的一部分。
-
在模板中使用组件
html<!-- app.component.html --> <my-component></my-component>
在模板文件中使用 my-component 标签来引入刚刚定义的组件。
3.5 装饰器(注解)
Angular 中的装饰器是一种特殊类型的声明,用于添加元数据和修改类声明。Angular 中的装饰器主要用于标识和配置组件、指令、服务等各种 Angular 元素。
3.5.1 @Component
用于将一个类标记为 Angular 组件,并提供该组件的元数据信息,包括模板、样式、选择器等。
typescript
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {}
属性
- selector:指定组件在HTML中的选择器,用于标识该组件应该被插入到哪个位置。
- template/templateUrl:指定组件的模板内容或模板文件的路径。
- style/styleUrls:指定组件的样式内容或样式文件的路径。
- providers: 用于配置该组件所需的服务提供者。
- 其他属性 :https://angular.io/api/core/Component
3.5.2 @Directive
用于定义指令,给 HTML 元素附加行为或样式。
typescript
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {}
属性
- selector:指令在HTML中的选择器,用于标识该指令应该被应用到哪些元素上。
- inputs: 用于配置指令接受的输入。
- outputs: 用于配置指令发出的输出。
- 其他属性 :https://angular.io/api/core/Directive
3.5.3 @Injectable
用于注入服务(Service),使其可以被其他组件或服务所依赖和使用。
typescript
@Injectable({
providedIn: 'root'
})
export class DataService {}
属性
- providedIn:指定服务的提供者,可以是 'root'、'any' 或一个特定的模块。
- providedIn: 'root':将服务注册为根注入器的提供者。
- 其他属性 :https://angular.io/api/core/Injectable
3.5.4 @Pipe
用于创建自定义管道,用于对模板中的数据进行转换。
typescript
@Pipe({
name: 'myCustomPipe'
})
export class MyCustomPipe implements PipeTransform {}
属性
- name:指定管道的名称,用于在模板中引用该管道。
- pure: 是否是纯管道。
- 其他属性 :https://angular.io/api/core/Pipe
3.6 服务
在 Angular 中,服务是有一种用于封装可重用功能和数据的类。通过服务,可以将应用程序中的公共功能 提取出来,以便在组件之间共享代码、数据和业务逻辑。
3.6.1 创建服务
在 Angular 中,可以使用 @Injectable
装饰器来创建服务。这个装饰器标记一个类可以作为依赖注入的对象,并且允许其他类依赖它。
typescript
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
// 服务逻辑
}
providedIn
3.6.2 注入服务
要在组件或其他服务中使用服务,需要在构造函数中引入该服务并将其声明为私有属性。
typescript
import { Component } from '@angular/core';
import { DataService } from './data.service';
@Component({
selector: 'app-my-component',
template: '<p>{{ data }}</p>'
})
export class MyComponent {
constructor(private dataService: DataService) {
this.data = this.dataService.getData();
}
}
3.6.3 提供服务
服务可以在跟模块或特定模块中提供,也可以在组件级别提供。使用providedIn
属性或模块的provides
数组来指定服务的提供者。
typescript
@Injectable({
providedIn: 'root'
})
export class DataService {
// 服务逻辑
}
或者在模块中提供:
typescript
@NgModule({
providers: [DataService],
// 其他模块配置
})
export class MyModule { }
- 生命周期:Angular 服务的生命周期由 Angular 的依赖注入系统管理。通常情况下,服务是单例的,即在整个应用程序中只会创建一个实例。
依赖注入:是一种编程模式,可以让类从外部源中获得它的依赖,而不必亲自创建它们。
3.7 管道
在绑定之前,表达式的结果可能需要一些转换。例如,可能希望把数字显示成金额、强制文本变成大写,或者过滤列表以及进行排序。Angular 管道对象 对这样的小型转换来说是个很方便的选择。
管道是一个简单的函数,它接受一个输入值,并返回转换结果。
3.7.1 常用的内置管道函数
- DatePipe:事件管道,根据区域设置规则格式化日期值
html
{{ value | currency [ : currencyCode [ : display [ : digitsInfo [ : locale ] ] ] ] }}
- UpperCasePipe:大写管道,将文本转为全部大写
- LowerCasePipe:小写管道,将文本全部转为小写
- SlicePipe:首字母转换为大写
- CurrencyPipi:货币管道,将数字转换成货币字符串
- DeprecatedPercentPipe:百分比管道,将数字格式化为百分比
- TitleCasePipe :将文本转为标题大小写,单词首字母大写,其余部分小写
- JsonPipe:json管道,将值转换为json格式
- DecimalPipe:字符串管道,将数字转换为字符串
它们用于模块表达式中,只要使用管道操作符| 就可以了
管道操作符会把它左侧的表达式结果传给它右侧的管道函数,还可以通过多个管道串联表达式。
javascript
<div class="alert alert-warning">
<p>{{ title|uppercase }}</p>
<p>{{ title|uppercase|lowercase }}</p> // 链式管道
<p>{{ this|json }}</p>
<p>{{ time|date:'yyyy-MM-dd'}}</p>
<p>{{ number|percent }}</p>
<p>{{ number|currency:'CNY' }}</p>
<p>{{ birthday| date:format }}</p>
</div>
export class AppComponent {
title = 'app';
name = '张三丰';
time = new Date();
number = 1.123;
birthday = new Date(2017,11,11)
flag = true;
format(){
return this.flag?'yyy-MM-dd':'MM-dd'
}
show(str: string) {
str += '---测试';
return str;
}
}
3.7.2 自定义管道
javascript
import { Pipe, PipeTransform } form '@angular/core';
@Pipe({ name: 'sexReform' }) // name属性值惯用小驼峰是写法, name的值为html中| 后面的名称
export class SexReformPipe implements PipeTransform {
transform(value: string, args?: any): string {
switch(value){
case 'male': return '男';
case 'female': return '女';
default: return '雌雄同体';
}
}
}
// 在组件中使用自定义管道
// demo.component.ts
export Class DemoComponent {
sexValue = 'male';
}
// demo.component.html
<span>{{ sexValue | sexReform }}</span>
3.8 HttpClient
-
根目录的module.ts里引入httpclient
typescriptimport { HttpClientModule } from '@angular/common/http'; imports: [ BrowserModule, AppRoutingModule, HttpClientModule // 加载httpclient ],
-
在组件的component.ts文件里导入httpclient,如果有post请求,还需要导入HttpHeaders
typescriptimport { HttpClient, HttpHeaders } from "@angular/common/http";
-
在组件的构造器里定义一个http
typescriptconstructor( private http: HttpClient, ) { }
-
设置headers
typescriptheaders = { Headers: new HttpHeaders({ "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8", }), };
-
使用http请求
typescriptthis.http .get<any>("接口地址", { headers: {}, params: {}, }) .subscribe((res) => { //请求成功的回调 } }), (err: any) => { // 请求失败的回调 console.log(err); };
通过proxy代理设置跨域
-
在项目的根目录里新增一个proxy.conf.json文件
-
在proxy.conf.json里设置代理
typescript{ "/api": { "target": "请求的接口地址", "secure": false, "changeOrigin": true } }
-
在package.json里配置启动代理
-
重新运行项目,就可以正常请求到接口了
powershellnpm start
3.9 路由
vue
{ path: "home", compont: home }
<a routerLink='home'></a> // 等同于vue的 router-link to=''
<router-outlet></router-outlet> // 路由出口
// 重定向路由
{ path: "",redirectTo: "home", pathMath: "full" }
// 参数路由
{ path: "home/:id", compont: home }
// 使用
<a routerLink='home/12'></a>
// 在组件里获取参数,router-params.component.ts
// 先引入Docheck钩子函数和路由核心库
import { DoCheck } from '@angular/core'
import { Router, ParamMap } from '@angular/router'
// 获取参数snapshot.paramMap.get('路由里定义的变量名')
export class RouterParamsComponent implements OnInit,DoCheck{
id;
constructor(private route:ActivatedRoute,private router:Router){}
ngDoCheck():void{
this.id = this.route.snapshot.paramMap.get('id')
}
}
配置子路由
javascript
{
path: "home",
compont: home,
children:[
{ path: "homea", compont:homea }, // 子路由地址:/home/homea
{ path: "homeb/:id", compont:homeb }, // /home/homeb/1
]
}
注意:子路由需要在他的父路由的html中添加路由出口,否则会跳转无响应
函数路由
javascript
// 通过事件跳转路由
this.router.navigateByUrl('路由地址')
// 还可以设置属性{ skipLocationChange:true },实现页面跳转但路由不发生变化
this.router.navigateByUrl('home',{skipLocationChange:true})
// 还可以使用navigate进行路由跳转
this.router.navigate(['home'])
// 传参
this.router.navigateByUrl('home/1')
this.router.navigate(['home','1'])
五、总结
AngularJS
是一个功能丰富的JavaScript
框架,提供了许多强大的特性和工具,用于构建现代化的Web应用程序。本文提供了一个简单、全面、容易上手的入门指南,帮助你开始学习和使用AngularJS
。我们介绍了安装和设置AngularJS
的步骤,以及数据绑定、控制器、指令和服务等核心概念。希望这篇文章能够帮助你快速入门AngularJS
,并开始构建令人惊艳的Web应用程序。