这个问题已经被打死了,但无论如何我都会分享这个问题,以防其他人正在为 AngularJS 范围的可怕混乱而苦苦挣扎。这将涵盖=
、<
、@
和&
。::
完整的文章可以在这里找到。
=
建立双向绑定。更改父项中的属性将导致子项发生更改,反之亦然。
<
建立一个单向绑定,父母对孩子。更改父属性中的属性会导致子属性发生更改,但更改子属性不会影响父属性。
@
将为子属性分配标签属性的字符串值。如果该属性包含一个表达式,则只要该表达式的计算结果为不同的字符串,子属性就会更新。例如:
<child-component description="The movie title is {{$ctrl.movie.title}}" />
bindings: {
description: '@',
}
在这里,description
子作用域中的属性将是表达式的当前值"The movie title is {{$ctrl.movie.title}}"
,其中movie
是父作用域中的一个对象。
&
有点棘手,实际上似乎没有令人信服的理由来使用它。它允许您在父范围内评估表达式,用子范围中的变量替换参数。一个例子(plunk):
<child-component
foo = "myVar + $ctrl.parentVar + myOtherVar"
</child-component>
angular.module('heroApp').component('childComponent', {
template: "<div>{{ $ctrl.parentFoo({myVar:5, myOtherVar:'xyz'}) }}</div>",
bindings: {
parentFoo: '&foo'
}
});
给定parentVar=10
,表达式parentFoo({myVar:5, myOtherVar:'xyz'})
将计算为5 + 10 + 'xyz'
并且组件将呈现为:
<div>15xyz</div>
你什么时候想使用这个复杂的功能?&
人们经常使用它来将父作用域中的回调函数传递给子作用域。然而实际上,使用'<'来传递函数也可以达到同样的效果,这样更直接,并且避免了笨拙的花括号语法来传递参数({myVar:5, myOtherVar:'xyz'}
)。考虑:
回调使用&
:
<child-component parent-foo="$ctrl.foo(bar)"/>
angular.module('heroApp').component('childComponent', {
template: '<button ng-click="$ctrl.parentFoo({bar:'xyz'})">Call foo in parent</button>',
bindings: {
parentFoo: '&'
}
});
回调使用<
:
<child-component parent-foo="$ctrl.foo"/>
angular.module('heroApp').component('childComponent', {
template: '<button ng-click="$ctrl.parentFoo('xyz')">Call foo in parent</button>',
bindings: {
parentFoo: '<'
}
});
请注意,对象(和数组)是通过引用传递给子作用域的,而不是复制的。这意味着即使它是单向绑定,您也在父范围和子范围中使用相同的对象。
要查看不同的前缀,请打开此plunk。
一次性绑定(初始化)使用
::
[官方文档]
AngularJS 的更高版本引入了具有一次性绑定的选项,其中子范围属性仅更新一次。这通过消除查看父属性的需要来提高性能。语法与上面不同;要声明一次性绑定,请在组件标记::
中的表达式前面添加:
<child-component
tagline = "::$ctrl.tagline">
</child-component>
这会将 的值传播tagline
到子范围,而无需建立单向或双向绑定。注意:如果tagline
最初undefined
是在父范围内,Angular 会一直观察到它发生变化,然后对子范围内的相应属性进行一次更新。
概括
下表显示了前缀如何根据属性是对象、数组、字符串等来工作。