Angular官方开发文档讲的很细致,但是这是一把双刃剑。
双刃剑
上一篇中Angular CLI
的文档,并非Angular官方开发文档的一部分。(可能我没发现吧)
而从这篇文章开始,我将开始阅读Angular的官方开发文档
。
首先,我阅读完了教程
、核心知识-构架
,粗略的了解下Angular
的开发流程和一些基本的概念。
然后,就是看核心知识-组件与模板
了,看完了第一遍其实,还是有点懵。
有几点感受:
- 可能是因为是英译,有些地方感觉翻译的有点不够接地气,不太便于国人理解
- 文字过于冗长,有时候让人很难抓到重点
- 像看小说,一定要循序渐进慢慢看,不然稍微跳一下,剧情就接不上了
- 看过的vue文档的朋友,一定会感觉vue的文档简洁而清晰
所以在看Angular文档的同时,提炼总结下,还是很有必要的。
1.Attribute & Property
官方文档中强调:
定模板绑是通过 property 和事件来工作的,而不是 attribute。
在Angular开发中,个人感觉一定要明确这两者的别
,才能更好的理解Angular的工作方式。不然很容易产生混淆
,因此我把这一小节放到最前面。
attribute
是指HTML attribute
property
是指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
的attribute
src与image
的property
src相同,所有感觉让人产生混淆
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 修仙之路
强烈安利