【Angular】深入总结angular核心,都是干货

为什么写这篇文章:

使用angular开发也有快2年的时间,突然有一天有人问我,你能不能给我简单讲一下angular框架?虽然每天都在使用,却不知如何表述,故决定写这样一篇文章。

一句话知识点:

Angular本身就是用 TypeScript 写成的,核心功能和可选功能作为一组 TypeScript库,根据需要导入到应用中;

Angular 的基本构建块是 NgModule特性模块,为组件提供编译的上下文环境。Angular应用就是由一组NgModule定义的, NgModule 可以将其组件和一组相关代码(如服务)关联起来,形成功能单元;

组件定义视图,由html模板+css样式+ts组件类构成,也可以根据需要引入服务类。

模板把传统的html和angular模板语法结合起来,是HTML的升级版(插值,属性绑定,双向数据绑定,事件绑定,指令,结构指令,属性指令,管道等等);

css样式可以使用scss和less进行预扩展;

组件类定义应用的数据和业务逻辑;

组件可以把服务类通过DI依赖注入到组件中;

通过Router服务在多个视图之间进行导航功能;

不过路由器会把类似 URL 的路径映射到视图而不是页面。 当用户执行一个动作时(比如点击链接),本应该在浏览器中加载一个新页面,但是路由器拦截了浏览器的这个行为,并显示或隐藏一个视图层次结构;

如果路由器认为当前的应用状态需要某些特定的功能,而定义此功能的模块尚未加载,路由器就会按需惰性加载此模块

导航路径和你的组件关联起来。 路径(path)使用类似 URL 的语法来和程序数据整合在一起,就像模板语法会把你的视图和程序数据整合起来一样。 然后你就可以用程序逻辑来决定要显示或隐藏哪些视图,以根据你制定的访问规则对用户的输入做出响应;

装饰器类型:

@Component()

@Injectable()

以上是视图的构成:

组件和模板共同构成了视图:

  1. 组件类上的装饰器@Component()为其添加元数据,包括指向对应模板的指针;
  2. 模板中的指令和绑定标记会根据程序数据和逻辑修改这些视图;
  3. DI依赖注入器会为组件提供特定的服务,如路由器服务,提供视图之前的导航,网络服务,与服务器的I/O数据交互。

NgModule简介

它就是一个容器,存放一些内聚的代码块,使用某个特定的功能。它可以包含组件,服务提供商,其他代码文件等。

@NgModule函数的入参:

declarations(可声明对象表) —— 那些属于本 NgModule 的组件、指令、管道。

exports(导出表) —— 那些能在其它模块的组件模板中使用的可声明对象的子集。

imports(导入表) —— 那些导出了本模块中的组件模板所需的类的其它模块。

Providers(服务提供商) —— 本模块向全局服务中贡献的那些服务的创建器。 这些服务能被本应用中的任何部分使用。(你也可以在组件级别指定服务提供商,这通常是首选方式。)

Bootstrap(启动项) —— 应用的主视图,称为根组件。它是应用中所有其它视图的宿主。只有根模块才应该设置这个 bootstrap 属性;

 

NgModule和组件:

NgModule可以declaration任意数量的其他组件,这些组件可以是通过路由加载,或者是通过模板创建,他们都属于这个NgModule的组件会共享同一个编译上下文环境,即为,imports的模块(服务类,框架的模块)都可以在组件中使用

组件还可以包含视图层次结构。一个视图层次结构可以混合使用由不同NgModule中的组件定义的视图,比如UI库。宿主视图为起点,下面包含内嵌视图

 

Component简介

组件构成视图的一部分。在组件类汇总定义它的应用逻辑,通过定义属性和方法组成的API与视图交互

组件可以通过TS的构造器参数性属性,通过依赖注入系统将服务提供给该组件。

组件都有生命周期钩子(lifecycle hooks),因为ng会在应用的过程中,对组件进行create、update、destroy操作,故可以根据需要在对应的钩子环节添加额外的应用逻辑。

组件的元数据:

@Component装饰器后面紧跟的类就代表一个组件类(类似于JAVA的注解),并为其制定metadata元数据,即为函数的入参

元数据告诉angular到哪里获取它的主要构造块,来创建和展示这个组件及其视图。具体来说,它把模板和该组件关联起来,该组件及其模板,共同描述一个视图

具体配置项如下:

selector:是一个 CSS 选择器,它会告诉 Angular,一旦在模板 HTML 中找到了这个选择器对应的标签,就创建并插入该组件的一个实例的视图。

templateUrl:该组件的 HTML 模板文件相对于这个组件文件的地址。 另外,你还可以用 template 属性的值来提供内联的 HTML 模板。 这个模板定义了该组件的宿主视图

providers:当前组件所需的服务提供商的一个数组。

 

模板与视图

与组件直接关联的模板就叫宿主视图,该组件还可以定义一个带层次结构的视图,在模板里引入其他组件关联的模板(可以是任何模块中定义的组件),他们就叫内嵌视图。

模板语法

传统HTML与angular模板语法结合,他可以使用数据绑定来协调应用和DOM中的数据,使用Pipes管道对数据进行转换,使用Directives指令在内容上添加逻辑代码。

数据绑定

数据绑定标记有四种形式,每种形式有方向性的,如下图:

 

双向数据绑定主要用于模板驱动表单,在Form元素中使用,代指起value属性(语法糖:将属性绑定和事件绑定合作成一种独特的写法)。

 

父子直接通信原理,如下图:

 

管道

@Pipe()

作用在模板中声明的显示值,做一个对应的转换的一个转换函数。

使用时,使用管道操作符 |

 

指令

@Directive()

理论上,组件就是一个指令。

Angular的模板是动态的,只有当渲染他们的时候解析,根据指令给出的指示对DOM进行转换。

分类:结构指令 / 属性指令.

结构指令:通过添加,移除,替换DOM元素来修改布局。

属性指令:修改元素的外观或行为。

 

服务与DI

@Injectable()

组件仅仅提供用于视图模板中数据绑定的属性和方法,让组件更加精简和高效。

可以将诸如从服务器上获取数据,验证用户输入等委托给各种服务,提高模块化和复用性。

 

依赖注入

 

组件是服务的消费者。

机制:

注入器injector:在ng启动过程中会自动创建全应用级注入器;

注入器会创建依赖,通过维护一个容器来管理这些依赖,复用;

提供商provider:告诉注入器如何创建或获取依赖,即为新实例。

 

提供服务

服务可以在自己的metadata元数据中注册为提供商;

为特定的模板或组件注册提供商,在@NgModule()或@Component()元数据中提供;

示例:

 

 

方式一:类本身上创建一个单一的共享实例,任何类中都可以直接调用;

这种方式可以让可以让ng通过移除那些未被使用过的服务来优化大小;

 

方式二:在模块中创建服务商,该服务的作用范围仅在该NgModule中的所有组件可用;

 

方式三:在组件注册provider,为该组件的每一个新实例提供该服务的一个新实例;

 

通过 interface 创建模型类,作为某个组件类的属性的类型(TS的类型检查);

 

基础常识:

  1. ngModel依赖FormsModule模块;
  2. 组件必须声明且只能声明(declarations)在一个NgModule中;
  3. 使用CLI创建组件会自动把它添加到NgModule中,如果手动创建组件,那还需要在对应的模块中声明一次;
  4. 如果不同模块需要声明同一个组件,可以将这种组件声明到一个公共的模块里面,然后分开在其他需要的模块引入该公共模块,再添加到imports数组中;另外,特别注意,公共慕课必须把组件export出去;
  5. @Input()装饰器代表的是一个输入属性;

父子通信:

[hero]="selectedHero" 是 Angular 的属性绑定语法;

这是一种单向数据绑定。从 父组件的 selectedHero 属性绑定到目标元素的 hero 属性,并映射到了子组件的 hero 属性;

 

为什么需要服务

因为组件的职责是聚焦于展示数据,处理与视图的数据交互,而不关心如何获取或保存数据,把这个工作的职责委托给某个服务;

服务可以在多个“相互不知道”的类之间共享信息;

服务提供商provider:某种可以创建或交付一个服务的东西;

组件的构造函数的参数:

  1. 声明一个私有属性;
  2. 把它标记为一个服务的注入点;
  3. HttpClient调用方法时,可以更加明确定义返回的类型;

特别注意:

  1. 某个服务类里暴露一个属性作为一个数据缓存,那么在组件的模板里使用时,必须在注入该服务时,使用public关键字,因为Angular只会绑定到组件的公共属性;

服务的一个基本流程:

  1. 创建一个服务类;
  2. 根注入器中注册为该服务的提供商 / NgModule / Component 注册服务提供商;
  3. 通过DI机制把它注入到组件中;
  4. Angular在创建组件时,就会为该组件创建该服务的一个单例实例;
  5. (服务可以注入其他服务,特别注意各个服务提供商的注册引起的问题;)

Router基础开发

  1. 引入依赖router库的RouterModule和Routes模块;
  2. 根模块元数据初始化路由器时,在imports中,使用RouterModule.forRoot(),创建路由所需的服务提供商和指令,然后才开始监听浏览器地址的变化,子路由使用.forChild();
  3. 在exports中,导出RouterModule的目的,以便于它在整个应用程序中生效;
  4. 在该模板的根组件的模板中,添加RouterOutlet路由出口;
  5. 模板中导航:a标签上使用routerLink(它是RouterLink指令的选择器);

{ path: 'detail/:id', component: HeroDetailComponent }

path路径中的冒号 ( : )表示:某个名称是一个占位符,可以在路由参数中获取;

 

拿路由参数:

  1. 引入ActivatedRoute模块,它保存着组件实例的路由信息,可以拿到id属性;
  2. 通过this.route.snapshot.paramMap.get(‘id’)拿到id值,其中,paramMap是一个从URL中提权的路由参数值的字典;
  3. 反引号(`)定义模板字符串字面量;
  4. Location模块,与浏览器打交道的,控制浏览器的前进后退操作,例如,this.loaction.back() ;

 

HTTP基础应用

 

HttpClient是Angular通过HTTP与远程服务器通讯的重要机制;

在根模块中导入HttpClientModule模块;

 

HttpClient的Observable总是发出一个值,然后complete,不会再发出其他值;

内部捕获错误,pipe中的catchError拦截失败的observable,可以定义一个方法来返回安全值,让应用继续正常运行;

 

AsyncPipe管道

<li *ngFor="let hero of heroes$ | async" >

 

Heroes$中,$是一个约定,表示它是一个Observable;

在模板中可以使用async管道,自动订阅Observable,就不必在组件类中subscribe;

 

Rxjs的各种操作符(核心库)

通过Observable来编写异步和基于事件的库;

基本概念:

  1. Observable (可观察对象):表示一个概念,这个概念是一个可调用的未来值或事件的集合;
  2. Observer (观察者):一个回调函数的集合,它知道如何去监听由 Observable 提供的值;
  3. Subscription (订阅):表示 Observable 的执行,主要用于取消 Observable 的执行;
  4. Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、concat、flatMap 等这样的操作符来处理集合;
  5. Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式;
  6. Schedulers(调度器):用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。

学习Rx,主要就是学习各种操作符,这里就不展开介绍。

总结:

以上就是Angular框架的整体介绍,掌握了它的基本运行原理。不仅会用,还能很好的表达出来。





 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值