angular总结-my

angular知识点:

1、 @Component 装饰器。这表明它下面的类是一个组件。它提供了有关该组件的元数据,包括它的模板、样式和选择器

@Component 的元数据中指定的样式只会对该组件的模板生效。

2、Angular 只会绑定到组件的公共属性

constructor(public messageService: MessageService) {}

src/app/messages/messages.component.html

  <div *ngIf="messageService.messages.length">
  <h2>Messages</h2>
  <button class="clear"
     (click)="messageService.clear()">clear</button>
  <div *ngFor='let message of messageService.messages'> {{message}} </div>
</div>

3、在组件的 ngOnInit 生命周期钩子中调用 HeroService 方法,而不是构造函数中

4、RouterModule.forRoot()

你必须首先初始化路由器,并让它开始监听浏览器中的地址变化。

RouterModule 添加到 @NgModule.imports 数组中,并用 routes 来配置它。你只要调用 imports 数组中的RouterModule.forRoot() 函数就行了。

content_copyimports: [ RouterModule.forRoot(routes) ],

这个方法之所以叫 forRoot(),是因为你要在应用的顶级配置这个路由器。 forRoot() 方法会提供路由所需的服务提供商和指令,还会基于浏览器的当前 URL 执行首次导航。

5、依赖不一定是服务 —— 它还可能是函数或值。

预先(AOT)编译器

Angular 应用主要由组件及其 HTML 模板组成。由于浏览器无法直接理解 Angular 所提供的组件和模板,因此 Angular 应用程序需要先进行编译才能在浏览器中运行。

在浏览器下载和运行代码之前的编译阶段,Angular 预先(AOT)编译器会先把你的 Angular HTML 和 TypeScript 代码转换成高效的 JavaScript 代码。 在构建期间编译应用可以让浏览器中的渲染更快速。

Angular 提供了两种方式来编译你的应用:

  • 即时编译 (JIT),它会在运行期间在浏览器中编译你的应用。
  • 预先(AOT)编译,它会在构建时编译你的应用。

为什么需要 AOT 编译?

渲染得更快

使用 AOT,浏览器下载预编译版本的应用程序。 浏览器直接加载运行代码,所以它可以立即渲染该应用,而不用等应用完成首次编译。

需要的异步请求更少

编译器把外部 HTML 模板和 CSS 样式表内联到了该应用的 JavaScript 中。 消除了用来下载那些源文件的 Ajax 请求。

需要下载的 Angular 框架体积更小

如果应用已经编译过了,自然不需要再下载 Angular 编译器了。 该编译器差不多占了 Angular 自身体积的一半儿,所以,省略它可以显著减小应用的体积。

提早检测模板错误

AOT 编译器在构建过程中检测和报告模板绑定错误,避免用户遇到这些错误。

更安全

AOT 方式会在发给客户端之前就把 HTML 模板和组件编译成 JavaScript 文件。 不需要读取模板,也没有客户端组装 HTML 或执行 JavaScript 的危险操作,受到注入类攻击的机会也比较少。

Build.

使用Angular CLI进行Build(构建)和Serve详解

Build主要会做以下动作:

  • 编译项目文件并输出到某个目录
  • Build targets决定了输出的结果
  • bundling 打包
  • 生产环境的build还会进行uglify和tree-shaking(把没用的代码去掉)
  1. 针对开发环境, 就是用命令 ng build.

默认情况下, 它的输出目录在.angular-cli.json文件里ourDir属性配置的, 默认是/dist目录.

build之后会看见dist里面有这些文件:

  • inline.bundle.js 这是webpack的运行时.
  • main.bundle.js 就是程序代码.
  • pollyfills.bundle.js 就是浏览器的Pollyfills.
  • styles.bundle.js 样式
  • vendor.bundle.jsangular和第三方库

可以使用source-map-explorer来分析依赖, 并且查看哪些模块和类在bundle里面.

执行ng build:
在这里插入图片描述

可以看到生成了这些文件.
在这里插入图片描述

打开main.bundle.js可以看到我写的代码:
在这里插入图片描述

把dist里面的index.html格式化一下看看,可以看到它引用了生成的5个js文件.在这里插入图片描述

因为ng build是开发时的build, 所以没有做任何优化, 文件挺大的.

这时看一下文件目录, 并没有dist目录,

那么这些文件是怎么被serve的呢?

这是因为, 这时候webpack是在内存中进行的serve.

使用source-map-explorer进行分析

看一下开发和生产build的对比.
ng buildng build --prod
Environmentenvironment.tsenvironment…prod.ts
缓存只缓存css里引用的图片所有build的文件
source maps生成不生成
如何处理css全局css输出到js文件生成的是css文件
uglify
Tree-Shaking不去掉无用代码去掉无用代码
AOT
Bundling打包
–build-optimizer是(和AOT以及Angular5)
–named-chunks
–output-hashingmedia所有

下面命令都是针对开发时的build, 它们的作用是一样的:

ng build
ng build --dev
ng build --dev -e=dev
ng build --target=development --environment=dev

下面则是生产build:

ng build --prod
ng build --prod -e=prod
ng build --target=production --environment=prod

其它常用的参数还有:

  • –sourcemap -sm 生成source map
  • –aot Ahead of Time编译
  • –watch -w Watch并rebuild
  • –environment -e Build环境
  • –target -t Build target
  • –dev 表示dev env和target
  • –prod 表示prod env和target
Production Build.

先使用–aot:

ng build --aot
在这里插入图片描述

使用aot之后可以看到 vendor.bundle的大小降了很多, 只有1.5m左右了.

执行aot会去掉一些程序执行不需要的代码, 例如angular的compiler这时就不在build输出的文件里了(可以使用source-map-explorer查看).

试试生产环境:

ng build --prod
在这里插入图片描述

可以看到所有的文件都非常小了, 并且没有vendor了(因为prod下–build-optimizer起作用所以vendor没有了, 但可以使用–vendor-chunk true给弄出来).

Serve.

ng serve. 已经一直在用了, 下面看看它常用的参数:

  1. –open -o 打开默认浏览器

  2. –port -p 端口

  3. –live-reload -lr 发生变化时重新加载网页(默认开启的)

  4. –ssl 使用https

  5. –proxy-config -pc 代理配置

  6. –prod 在内存中serve 生产模式build的文件

生成 Components, Directive, Service, class, interface, enum等等.

ng generate <蓝本名> 命令.

该命令的格式是 ng generate <蓝本名> <参数>.

  • Components.

    ng generate xxx xxx的命令还是有点长, 这里angular cli内置了命令的别名, 例如:

    ng generate component person 这个命令,

    里面的generate 可以使用字母 g 代替,

    里面的component 可以使用字母 c 代替.

ng generate component person
ng generate component person --inline-template --inline-style
 
ng g c person
ng g c person -it -is

ng g c student -ve Emulated -cd OnPush

可能常用的命令参数有:

  1. –flat 表示是否不需要创建文件夹

  2. –inline-template (-it) 模板是否应该放在ts文件里

  3. –inline-style (-is) 样式是否应该放在ts文件里.

  4. –spec 是否需要创建spec文件(测试文件)

  5. –view-encapsulation (-ve) View Encapsulation策略 (简单理解为样式文件的作用范围策略).

  6. –change-detection (-cd) 变化检查策略.

  7. –prefix 设定这个component的前缀

  8. –dry-run (-d), 打印出生成的文件列表, 而不直接生成.

  9. Directive

    ng g d filter-box

    directive生成了两个文件和component一样, 也在app.module进行了声明.

  10. Service

ng g s order-data

ng g s order-data2 -m app //使用 -m 参数来指定需要注册的module:

生成的order-data2 service就会在app.module.ts里面进行注册了.

  • model:

ng g cl models/user

  • interface:

ng g i models/animal

  • enum:

    ng g e models/gender

  • Pipe

ng g p camel-case

生成两个文件之外, 这个命令默认也会更新app.module.

  • Module

    ng g m login

表达式使用指南Link

当使用模板表达式时,请遵循下列指南:

没有可见的副作用
模板表达式除了目标属性的值以外,不应该改变应用的任何状态。

这条规则是 Angular “单向数据流”策略的基础。 永远不用担心读取组件值可能改变另外的显示值。 在一次单独的渲染过程中,视图应该总是稳定的。

最好使用幂等的表达式,因为它没有副作用,并且能提升 Angular 变更检测的性能。

在 Angular 的术语中,幂等的表达式应该总是返回完全相同的东西,直到某个依赖值发生改变。

在单独的一次事件循环中,被依赖的值不应该改变。 如果幂等的表达式返回一个字符串或数字,连续调用它两次,也应该返回相同的字符串或数字。 如果幂等的表达式返回一个对象(包括 Date 或 Array),连续调用它两次,也应该返回同一个对象的引用。

用户输入:

事件绑定

click

keydown.enter

blur

angular生命周期函数:
ngOnChanges()当 Angular(重新)设置数据绑定输入属性时响应。 该方法接受当前和上一属性值的 SimpleChanges 对象在 ngOnInit() 之前以及所绑定的一个或多个输入属性的值发生变化时都会调用。
ngOnInit()在 Angular 第一次显示数据绑定和设置指令/组件的输入属性之后,初始化指令/组件。在第一轮 ngOnChanges() 完成之后调用,只调用一次
ngDoCheck()检测,并在发生 Angular 无法或不愿意自己检测的变化时作出反应。在每个变更检测周期中,紧跟在 ngOnChanges()ngOnInit() 后面调用。
ngAfterContentInit()当 Angular 把外部内容投影进组件/指令的视图之后调用。第一次 ngDoCheck() 之后调用,只调用一次。
ngAfterContentChecked()每当 Angular 完成被投影组件内容的变更检测之后调用。ngAfterContentInit() 和每次 ngDoCheck() 之后调用
ngAfterViewInit()当 Angular 初始化完组件视图及其子视图之后调用。第一次 ngAfterContentChecked() 之后调用,只调用一次。
ngAfterViewChecked()每当 Angular 做完组件视图和子视图的变更检测之后调用。ngAfterViewInit() 和每次 ngAfterContentChecked() 之后调用。
ngOnDestroy()每当 Angular 每次销毁指令/组件之前调用并清扫。 在这儿反订阅可观察对象和分离事件处理器,以防内存泄漏。在 Angular 销毁指令/组件之前调用
组件交互
  • 1 通过输入型绑定把数据从父组件传到子组件

  • 2 通过 setter 截听输入属性值的变化

     @Input()
      set name(name: string) {
        this._name = (name && name.trim()) || '<no name set>';
      }
    
  • 3 通过*ngOnChanges()*来截听输入属性值的变化

  • 4 父组件监听子组件的事件 @Output

  • 5 父组件与子组件通过本地变量互动

     <h3>Countdown to Liftoff (via local variable)</h3>
      <button (click)="timer.start()">Start</button>
      <button (click)="timer.stop()">Stop</button>
      <div class="seconds">{{timer.seconds}}</div>
      <app-countdown-timer #timer></app-countdown-timer>
    
  • 6 父组件调用@ViewChild

     @ViewChild(CountdownTimerComponent, {static: false})
      private timerComponent: CountdownTimerComponent;
    
  • 7 父组件和子组件通过服务来通讯

指令

在 Angular 中有三种类型的指令:

  • 组件 — 拥有模板的指令

  • 结构型指令 — 通过添加和移除 DOM 元素改变 DOM 布局的指令

    三个常用的内置结构型指令 ——*ngIf ,*ngFor,[ngSwitch]

    星号(*)这个简写方法,而这个字符串是一个微语法,而不是通常的模板表达式。 Angular 会解开这个语法糖,变成一个 <ng-template>标记,包裹着宿主元素及其子元素。 每个结构型指令都可以用这个模板做点不同的事情。

    <div *ngIf="hero" class="name">{{hero.name}}</div>
    //星号是一个用来简化更复杂语法的“语法糖”。 从内部实现来说,Angular 把 *ngIf 属性 翻译成一个 <ng-template> 元素 并用它来包裹宿主元素
     <ng-template [ngIf]="hero">
      <div class="name">{{hero.name}}</div>
    </ng-template>
      
      
    <div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
      ({{i}}) {{hero.name}}
    </div>
    
    <ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
      <div [class.odd]="odd">({{i}}) {{hero.name}}</div>
    </ng-template>
    
  ​

- **属性型指令** — 改变元素、组件或其它指令的外观和行为的指令。

组件是这三种指令中最常用的。 你在快速上手例子中第一次见到组件。

结构型指令修改视图的结构。例如,NgFor 和 NgIf。 要了解更多,参见结构型指令 guide。

属性型指令改变一个元素的外观或行为。例如,内置的 NgStyle 指令可以同时修改元素的多个样式。



自定义属性指令:eg: appHighlight 当把鼠标移到 `p` 上的时候,背景色就出现了,而移开时就消失了。



`@HostListener` 装饰器让你订阅某个属性型指令所在的宿主 DOM 元素的事件

​```typescript
<p [appHighlight]="color">Highlight me!</p>
//[appHighlight] 属性同时做了两件事:把这个高亮指令应用到了 <p> 元素上,并且通过属性绑定设置了该指令的高亮颜色。 你复用了该指令的属性选择器 [appHighlight] 来同时完成它们


import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class HighlightDirective {

  constructor(private el: ElementRef) { }

  @Input('appHighlight') highlightColor: string;//通过别名绑定到了 highlightColor 属性

  @HostListener('mouseenter') onMouseEnter() {
    this.highlight(this.highlightColor || 'red');
  }

  @HostListener('mouseleave') onMouseLeave() {
    this.highlight(null);
  }

  private highlight(color: string) {
    this.el.nativeElement.style.backgroundColor = color;
  }
}
结构性指令为什么是移除而不是隐藏?

对于简单的段落,隐藏和移除之间的差异影响不大,但对于资源占用较多的组件是不一样的。 当隐藏掉一个元素时,组件的行为还在继续 —— 它仍然附加在它所属的 DOM 元素上, 它也仍在监听事件。Angular 会继续检查哪些能影响数据绑定的变更。 组件原本要做的那些事情仍在继续。

虽然不可见,组件及其各级子组件仍然占用着资源,而这些资源如果分配给别人可能会更有用。 在性能和内存方面的负担相当可观,响应度会降低,而用户却可能无法从中受益。

当然,从积极的一面看,重新显示这个元素会非常快。 组件以前的状态被保留着,并随时可以显示。 组件不用重新初始化 —— 该操作可能会比较昂贵。 这时候隐藏和显示就成了正确的选择。

内置的管道

Angular 内置了一些管道,比如 DatePipe、UpperCasePipe、LowerCasePipe、CurrencyPipe 和 PercentPipe。 它们全都可以直接用在任何模板中。

<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
Observable与RxJS

可观察对象支持在应用中的发布者和订阅者之间传递消息。 在需要进行事件处理异步编程处理多个值的时候,可观察对象相对其它技术有着显著的优点。

可观察对象是声明式的 —— 也就是说,虽然你定义了一个用于发布值的函数,但是在有消费者订阅它之前,这个函数并不会实际执行。 订阅之后,当这个函数执行完或取消订阅时,订阅者就会收到通知。

可观察对象可以发送多个任意类型的值 —— 字面量、消息、事件

RxJS

响应式编程是一种面向数据流和变更传播的异步编程范式(Wikipedia)。RxJS(响应式扩展的 JavaScript 版)是一个使用可观察对象进行响应式编程的库,它让组合异步代码和基于回调的代码变得更简单 (RxJS Docs)

RxJS 提供了一种对 Observable 类型的实现,直到 Observable 成为了 JavaScript 语言的一部分并且浏览器支持它之前,它都是必要的。这个库还提供了一些工具函数,用于创建和使用可观察对象。这些工具函数可用于:

  • 把现有的异步代码转换成可观察对象
  • 迭代流中的各个值
  • 把这些值映射成其它类型
  • 对流进行过滤
  • 组合多个流

RxJS 提供了一些用来创建可观察对象的函数。这些函数可以简化根据某些东西创建可观察对象的过程,比如事件、定时器、承诺等等 from 、ajax、 fromEvent、 interval

RxJS 定义了一些操作符,比如 map()filter()concat()flatMap()

常用操作符

类别操作
创建from,fromEvent, of from, fromPromise,fromEvent, of
组合combineLatest, concat, merge, startWith , withLatestFrom, zip
过滤debounceTime, distinctUntilChanged, filter, take, takeUntil
转换bufferTime, concatMap, map, mergeMap, scan, switchMap
工具tap
多播share

可观察对象的命名规范:可观察对象的名字以“$”符号结尾

错误处理

  • 订阅时提供 error() 处理器

  • catchError 操作符

  • retry 操作符:可以尝试失败的请

Angular 使用可观察对象作为处理各种常用异步操作的接口。比如:

  • EventEmitter 类派生自 Observable
  • HTTP 模块使用可观察对象来处理 AJAX 请求和响应。
  • 路由器和表单模块使用可观察对象来监听对用户输入事件的响应。

事件发送器EventEmitter

Async 管道

路由器(router)

响应式表单(reactive forms )

HTTP

Angular 的 HttpClient 从 HTTP 方法调用中返回了可观察对象。例如,http.get(‘/api’) 就会返回可观察对象。相对于基于承诺(Promise)的 HTTP API,它有一系列优点:

  • 可观察对象不会修改服务器的响应(和在承诺上串联起来的 .then() 调用一样)。反之,你可以使用一系列操作符来按需转换这些值。
  • HTTP 请求是可以通过 unsubscribe() 方法来取消的。
  • 请求可以进行配置,以获取进度事件的变化。
  • 失败的请求很容易重试。

rxjs用法实战

可观察对象可以简化输入提示建议的实现方式。典型的输入提示要完成一系列独立的任务:

  • 从输入中监听数据。
  • 移除输入值前后的空白字符,并确认它达到了最小长度。
  • 防抖(这样才能防止连续按键时每次按键都发起 API 请求,而应该等到按键出现停顿时才发起)
  • 如果输入值没有变化,则不要发起请求(比如按某个字符,然后快速按退格)。
  • 如果已发出的 AJAX 请求的结果会因为后续的修改而变得无效,那就取消它。
import { fromEvent } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { map, filter, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
 
const searchBox = document.getElementById('search-box');
 
const typeahead = fromEvent(searchBox, 'input').pipe(
  map((e: KeyboardEvent) => e.target.value),
  filter(text => text.length > 2),
  debounceTime(10),
  distinctUntilChanged(),
  switchMap(() => ajax('/api/endpoint'))
);
 
typeahead.subscribe(data => {
 // Handle the data from the API
});
惰性加载模块:

forRoot()forChild()**

你可能已经注意到了,CLI 会把 RouterModule.forRoot(routes) 添加到 app-routing.module.tsimports 数组中。 这会让 Angular 知道 AppRoutingModule 是一个路由模块,而 forRoot() 表示这是一个根路由模块。 它会配置你传入的所有路由、让你能访问路由器指令并注册 RouterService。 在 AppRoutingModule 中使用 forRoot(),在本应用中这只会在顶层模块中写一次。

CLI 还会把 RouterModule.forChild(routes) 添加到各个特性模块中。这种方式下 Angular 就会知道这个路由列表只负责提供额外的路由并且其设计意图是作为特性模块使用。你可以在多个模块中使用 forChild()

forRoot() 包含的注入器配置是全局性的,比如对路由器的配置。forChild() 中没有注入器配置,只有像 RouterOutletRouterLink 这样的指令。

service worker 与 KWA
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值