Angular官方开发文档讲的很细致,但是这是一把双刃剑。
双刃剑
上一篇中Angular CLI的文档,并非Angular官方开发文档的一部分。(可能我没发现吧)
而从这篇文章开始,我将开始阅读Angular的官方开发文档。
首先,我阅读完了教程、核心知识-构架,粗略的了解下Angular的开发流程和一些基本的概念。
然后,就是看核心知识-组件与模板了,看完了第一遍其实,还是有点懵。
有几点感受:
- 可能是因为是英译,有些地方感觉翻译的有点不够接地气,不太便于国人理解
- 文字过于冗长,有时候让人很难抓到重点
- 像看小说,一定要循序渐进慢慢看,不然稍微跳一下,剧情就接不上了
- 看过的vue文档的朋友,一定会感觉vue的文档简洁而清晰
所以在看Angular文档的同时,提炼总结下,还是很有必要的。
1.Attribute & Property
官方文档中强调:
定模板绑是通过 property 和事件来工作的,而不是 attribute。
在Angular开发中,个人感觉一定要明确这两者的别,才能更好的理解Angular的工作方式。不然很容易产生混淆,因此我把这一小节放到最前面。
attribute是指HTML attributeproperty是指DOM property
Angular世界中所说的【属性】,基本上应该是指【property】
attribute在 Angular 中 唯一的作用是用来初始化元素和指令的状态。 当进行数据绑定时,只是在与元素和指令的 property 和事件打交道,而 attribute 就完全靠边站了。
2.插值
2.1.文本
1 | <p>My current hero is {{currentHero.name}}</p> |
2.2.原始Html
Angular 数据绑定对危险 HTML 有防备。 在显示它们之前,它会对内容先进行处理。
不管是插值表达式还是属性绑定,都不会允许带有 script 标签的 HTML 泄漏到浏览器中。
src/app/app.component.ts
1 | htmlWithEvil = '<h1>be careful</h1><br><script>alert("evil never sleeps")</script>'; |
src/app/app.component.html
1 | <!-- 方式1 --> |
方式1:直接插值,显然Angular不会这么轻易让你直接插html进来。htmlWithEvil会被转义后输出,html不会有任何效果
方式2:绑定innerHTML属性,htmlWithEvil中的<script>被过滤后,html生效
2.3.模板表达式
1 | 指的是{{expression}} 中的 expression |
方便起见本文中的expression均是指模板表达式
expression不仅可以在花括号里面用,可以在属性绑定的时候用
expression的语法和JavaScript相似,但不完全相同
与JavaScript的区别expression不予许出现:
- 赋值 (=, +=, -=, …)
- new 运算符
- 使用 ; 或 , 的链式表达式
- 自增和自减运算符:++ 和 –
- 不支持位运算 | 和 &
2.4.模板表达式运算符
模板表达式运算符是JavaScript中没有的的特性
2.4.1.管道操作符
管道操作符|,可对表达式结果进行一些转换
1 | <div>Title through uppercase pipe: {{title | uppercase}}</div> |
想了解更多Angular自带的管道,可以官网查管道的API
2.4.2.安全导航操作符和空属性路径
可以完美的解决空值异常,增加视图的容错性。
1 | {{order?.consignee?.mobile}} |
即使consignee是个空值,也不会报异常,只是不显示而已。可以完美的解决空值异常,增加视图的容错性。
2.4.3.非空断言操作符
如果你打开了严格检测,那就要用到这个模板操作符,而其它情况下则是可选的。
1 | <!--No hero, no text --> |
在 TypeScript 2.0 中,你可以使用
--strictNullChecks标志强制开启严格空值检查。TypeScript 就会确保不存在意料之外的 null 或 undefined。
3.属性绑定
3.1.基本语法
[property]="expression"
3.1.三种写法
1 | <!-- 例1 --> |
- 以上三种方式,效果是相同的
例1、例2,都是属于纯正的属性绑定语法例3,血统不纯正,不推荐使用
估计是为了兼顾AngularJs的使用习惯
虽然在渲染视图之前,Angular会把例3翻译成相应的属性绑定
但当property数据类型不是字符串时,会产生问题。后面3.2举例
上面这个例子中,
img的attributesrc与image的propertysrc相同,所有感觉让人产生混淆
3.2.容易混淆之处
1 | <!-- 例1 --> |
两者效果完全相同,再次印证:方括号里面的其实是property,而不是,不是,不是attribute。
1 | <button [disabled]="isDisabled">Save</button> |
- 如果当
isDisabled值为true的时候,三个按钮都禁用了,没毛病。 - 如果当
isDisabled值为false的时候,前两个按钮可用了,没毛病。但是!第三个按钮依然还是禁用。
应该是把false转成'false'后,赋值给了disabled这个property
所以,不要以为你用TypeScript在写Angular,就可以忘了JavaScript这个弱类型语言。
最终建议:为了避免不必要的麻烦,还是使用
标准语法为好.
3.3.组件属性
属性绑定,同样适用于自定义组件。不过需要注意的是,在绑定属性时,务必传入匹配的数据类型
1 | <app-hero-detail [hero]="currentHero"></app-hero-detail> |
app-hero-detail组件的 hero 属性想要一个 Hero 对象,那就在属性绑定中精确地给它一个 Hero 对象
4.attribute绑定
基本语法:[attr.colspan]="expression"
1 | <table> |
当有些元素的attribute并没有对应property时,就可以这么干
考虑 ARIA, SVG 和 table 中的 colspan/rowspan 等 attribute。 它们是纯粹的 attribute,没有对应的属性可供绑定。
5.class绑定
5.1.基本语法
[class.class-name]="isSpecial",isSpecial值为 true/false
追加
1 | <div class="a-class b-class" [class.c-class]='condition'>xxx</div> |
condition = true时,会在原有class基础上,追加c-class。实际输出:
1 | <div class="a-class b-class c-class">xxx</div> |
覆盖
1 | <div class="a-class b-class" [class]='classTxt'>xxx</div> |
classTxt = 'c-class'时,将会覆盖原有class。实际输出:
1 | <div class="c-class">xxx</div> |
这种做法,似乎很鸡肋,没想出使用场景。我就是列出来,做个区分
痛点
1 | <div class="a-class b-class" |
如果有N个class,需要用变量作为条件控制,这就变的很尴尬。
这个时候就要祭出NgClass了。
5.2.NgClass
用法示例:
1 | <!-- 字符串 --> |
a-class始终存在,[ngClass]控制是否追加c-class、d-class
可见NgClass,非常灵活
想不明白,为啥还要提供[class]这种操作方式。像vue就只是提供了
:class而已。
有时候选择多了,也未必是件好事儿。
6.style绑定
6.1.基本命令
[style.style-property(.unit)]="value"
1 | <button [style.color]="isSpecial ? 'red': 'green'">Red</button> |
不多说,提炼备忘
6.2.NgStyle
1 | <div style="background: red;" [ngStyle]="{'color': 'white'}">xxx</div> |
- 可在原有样式基础上
追加 - 可
覆盖原有的某个样式 - 可直接赋值
上下文变量
7.条件渲染
7.1.NgIf
1 | <app-hero-detail *ngIf="isActive"></app-hero-detail> |
7.2.NgSwitch
1 | <div [ngSwitch]="currentHero.emotion"> |
8.列表渲染
基本示例
1 | <table width="100%"> |
1 | export class AppComponent { |
内置变量
index(number) 引索first(boolean) 是否第一行last(boolean) 是否第二行even(boolean) 引索是否是偶数,不是指是否偶数行odd(boolean) 引索是否是奇数,不是指是否奇数行
以上内置变量,必须要在ngFor内显示声明,否则默认是拿不到的
ngFor的内容并不是模板表达式,而是Angular中的微语法
1 | let item of list; index as i;first as f;last as l;even as e;odd as o; |
上面,2个写法是等价的,1更短,2更直观,推荐2
trackBy
需要指定一个function,用于提升性能,提高元素的复用性,避免将所有列表单元重绘。
与vue中的track-by或:key同一个作用
9.事件处理
安利一篇文章,感觉总结的不错
探索至此,发现有一个梳理得非常棒的的博客:Angular 4.x 修仙之路
强烈安利