来源地址:http://blog.csdn.net/lastsweetop/article/details/54603931
angular表达式
angular表达式是一些类似JavaScript的代码片段,主要用在插补绑定,例如<span title="{{ attrBinding }}">{{ textBinding }}</span>
,或者直接用于angular指令的属性值,例如ng-click="functionExpression()"
有效表达式示例如下:
- 1+2
- a+b
- user.name
- items[index]
angular表达式 VS javascript表达式
angular表达式和javascript表达式很相似,但也有些不同之处,如下:
- Context:javascript表达式的Context可以是整个window,而angular的Context只是一个scope对象范围内。
- Forgiving:javascript中,如果对undefined的属性求值会产生ReferenceError和TypeError错误,而在angular中,表达式的求值会对undefined和null非常宽容。
- Filters:可以在展示数据之前先用filters对表达式进行数据格式化。
- 不能写控制流语句:不能在angular表达式写控制流语句:条件,循环,异常。
- 不能做函数定义:不能在angular表达式定义函数,即使在ng-init指令中。
- 不能用在正则表达式:不能在angular表达式创建正则表达式。
- 不能用new创建对象:不能在angular表达式用new操作符创建对象。
- 不能使用位,逗号,void操作符:不能再angular表达式使用位,逗号,void操作符。
示例
这个示例可以计算不同的angular表达式:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
Context
angular不能用javascript的eval()
方法对表达式进行求值,而且用angular的$parse
服务来处理这些表达式。
angular表达式不能直接访问全局变量window
,document
,location
。这种限制是angular有意这样规定的,防止访问常见bug的来源。
你可以在控制器的函数中去使用$window
和$location
服务,然后从表达式中调用,这些服务也可以访问全局变量。
可以用this
标识符访问上下文对象,也可以用$locals
标识符访问locals的对象
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
Forgiving
表达式求值对undefined和null是宽容的。在javascript中对a.b.c
求值时,如果a
不是一个对象,就会抛异常。作为一个通用语言,表达式求值主要用于数据绑定,通常是这样:
- 1
- 1
a
如果是undefined(可能我们在等待服务器的返回,它马上就会变成defined),这时候什么也不显示通常要比抛出一个异常明智的多。如果表达式求值不能宽容,那么我们需要写杂乱的绑定代码,如下:
- 1
- 1
同样,在undefined
或者null
的情况下,调用a
的函数a.b.c()也只是简单的返回undefined
。
不能写控制流语句
除了三元运算符,你不能在angular表达式写一个控制流语句。这和angular的核心思想有关:应用的逻辑应该在控制器中,而不是视图中。如果你确实需要在angular表达式写一个条件,循环,或者异常,委托给javascript方法。
不能做函数定义和正则表达式
你不能在angular表达式定义函数或者创建正则表达式,这样可以避免模板中有复杂的模型转换逻辑。这些逻辑可以放在控制器中或者一个专门的过滤器中,控制器和过滤器还方面进行测试。
$event
ngClick
和ngFocus
这样的指令会讲\$event
对象暴露给表达式的scope,这个对象是个jQuery事件对象或者说一个jqLite对象。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
注意在上面的例子中,我们可以传递$event
给clickMe
,但是不能显示{{\$event}}
,因为$event
超出了绑定的scope。
一次性绑定
一次性表达式以::开头,当它们稳定后就会停止重新计算,这里说的稳定是指第一次digest之后表达式的值不是undefined的情况下。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
使用一次性绑定的原因
一次性绑定的主要目的是,提供了创建绑定的方法,一旦绑定被稳定化,相应的资源就可以被注销和释放。减少需要观察的表达式数量,使得digest循环更快速,在相同时间内更多的信息可以展示出来。
价值稳定算法
只要该值不是undefined,一次性绑定表达式只会保留digest结束时表达式的值。如果该值在digest循环的时候设置,稍后在相同的循环中它被设置成undefined,那么表达式不满足稳定的条件,它会被继续监视。
- 给定一个以::开头的表达式,当digest进入后,expression被进行脏检查,存储表达式的值为V。
- 如果V不是undefined,把表达式标记为稳定的,并且分配一个任务,这个任务在退出digest循环时,注销该表达式的watch。
- 继续处理digest循环
- 当digest完成之后并且所有的值都已经解决。开始运行watch注销任务,检查一下表达式的值是否稳定的。如果是,那么注销掉watch,如果不是,保留这个watch在digest循环中,开始步骤1的循环。
怎样用好一次性绑定的优势
如果表达式在设置后不会更改,则是一次性绑定的最佳选择。这里有三个例子:
当插补文本或者属性:
- 1
- 1
当我们使用双向绑定指令而参数不会更改时:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 1
当我使用有一串表达式的指令时:
- 1
- 2
- 3
- 1
- 2
- 3