这个问题已经被打死了,但无论如何我都会分享这个问题,以防其他人正在为 AngularJS 范围的可怕混乱而苦苦挣扎。这将涵盖=、<、@、& 和::。完整的文章可以在here 找到。
= 建立双向绑定。更改父项中的属性将导致子项发生更改,反之亦然。
< 建立一个单向绑定,父到子。改变父属性会导致子属性发生变化,但改变子属性不会影响父属性。
@ 将为子属性分配标签属性的字符串值。如果属性包含expression,则只要表达式计算为不同的字符串,子属性就会更新。例如:
<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。
使用
::的一次性绑定(初始化)
[Official docs]
更高版本的 AngularJS 引入了具有一次性绑定的选项,其中子范围属性仅更新一次。这通过消除查看父属性的需要来提高性能。语法与上面不同;要声明一次性绑定,请在 组件标记中的表达式前面添加:::
<child-component
tagline = "::$ctrl.tagline">
</child-component>
这会将tagline 的值传播到子作用域,而无需建立单向或双向绑定。 注意:如果tagline最初在父作用域中是undefined,angular会观察它直到它发生变化,然后对子作用域中的相应属性进行一次性更新。
总结
下表显示了前缀如何根据属性是否为对象、数组、字符串等工作。