javascript AngularJS 1.4 指令:作用域、双向绑定和 bindToController
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31861783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
AngularJS 1.4 directives: scope, two way binding and bindToController
提问by LeoLozes
Update: It must have been something stupid in another part of the code. It works now, so the bindToController syntax is fine.
更新:代码的另一部分一定是愚蠢的。它现在可以工作了,所以 bindToController 语法很好。
We are using AngularJS 1.4, which introduced a new way to use bindToControllerin directives.
我们使用的是 AngularJS 1.4,它引入了一种在指令中使用 bindToController的新方法。
After quite a bit of reading (and maybe not understanding everything), we defined our directive like this:
经过相当多的阅读(可能还没有理解所有内容),我们像这样定义了我们的指令:
.directive('mdAddress', function mdAddress() {
var directive = {
restrict: 'EA',
scope: {},
bindToController: {
address: '='
},
templateUrl: 'modules/address/address.html',
controller: AddressController,
controllerAs: 'dir'
};
Calling it from another view like this:
像这样从另一个视图调用它:
<md-address address="vm.address"></md-address>
Having previously defined in the view controller:
之前在视图控制器中定义过:
vm.address = {
street: null,
countryCode: null,
cityCode: null,
postalCode: null
};
Referencing the variables in the directive template like this:
像这样引用指令模板中的变量:
<md-input-container>
<label>{{'ADDRESSNUMBER' | translate}}</label>
<input type="number" ng-model="dir.address.streetNumber">
</md-input-container>
We spent 4h trying to figure out why our directive was not working. Well, it was working, but the two-way binding between the controller and the directive was not, vm.address.street
was hopelessly set to null.
我们花了 4 小时试图弄清楚为什么我们的指令不起作用。嗯,它正在工作,但控制器和指令之间的双向绑定没有,vm.address.street
无可救药地设置为空。
After a while, we just tried the old way:
过了一会儿,我们只是尝试了旧的方式:
.directive('mdAddress', function mdAddress() {
var directive = {
restrict: 'EA',
scope: {
address: '='
},
bindToController: true,
templateUrl: 'modules/address/address.html',
controller: AddressController,
controllerAs: 'dir'
};
And it magically worked. Any idea WHY?
它神奇地起作用了。知道为什么吗?
回答by ConcurrentHashMap
Update:
更新:
Thanks to the reference to this blog post, I need to update my answer. Since AngularJS 1.4 it really seems, that you can use
感谢对这篇博文的引用,我需要更新我的答案。从 AngularJS 1.4 开始,你真的可以使用
scope: {},
bindToController: {
variable: '='
}
which will do the (exact) same thing as the old syntax:
这将与旧语法做(完全)相同的事情:
scope: {
variable: '='
},
bindToController: true
The useful lines from the AngularJS source code to explain this behavior:
AngularJS 源代码中解释这种行为的有用行:
if (isObject(directive.scope)) {
if (directive.bindToController === true) {
bindings.bindToController = parseIsolateBindings(directive.scope,
directiveName, true);
bindings.isolateScope = {};
} else {
bindings.isolateScope = parseIsolateBindings(directive.scope,
directiveName, false);
}
}
if (isObject(directive.bindToController)) {
bindings.bindToController =
parseIsolateBindings(directive.bindToController, directiveName, true);
}
Source: AngularJS 1.4.0
Original answer:
原答案:
Hopefully, I can explain you why this behavior you experienced is correct and where you did missunderstand the concept of scope binding there.
希望我能向您解释为什么您所经历的这种行为是正确的,以及您在哪里误解了范围绑定的概念。
Let me explain, what you did in your first code snippet:
让我解释一下,您在第一个代码片段中做了什么:
.directive('mdAddress', function mdAddress() {
var directive = {
restrict: 'EA',
scope: {},
bindToController: {
address: '='
},
templateUrl: 'modules/address/address.html',
controller: AddressController,
controllerAs: 'dir'
};
With scope: {}
, you created an isolated scope (without any inheritance) for your mdAddress
directive. That means: No data is passed between the parent controller and your directive.
使用scope: {}
,您为mdAddress
指令创建了一个独立的作用域(没有任何继承)。这意味着:父控制器和您的指令之间没有数据传递。
Having this in mind, regarding your second code snippet:
考虑到这一点,关于您的第二个代码片段:
<md-address address="vm.address"></md-address>
vm.address
from your parent controller/view will be assigned as expression to the address attribute of the directive, but as you defined an isolated scope before, the data is not passed into AddressController
and therefore not available in the bindToController
value.
vm.address
从您的父控制器/视图将作为表达式分配给指令的地址属性,但由于您之前定义了一个隔离范围,因此数据不会传入AddressController
,因此在bindToController
值中不可用。
Let's think of the scope
object definition as the "which data will be passed in" and the bindToController
as the "which data will be available in my view's controllerAs object".
让我们将scope
对象定义视为“将传入哪些数据”和bindToController
“哪些数据将在我的视图的 controllerAs 对象中可用”。
So, now let's have a look at the last (and working code snippet):
所以,现在让我们看看最后一个(和工作代码片段):
.directive('mdAddress', function mdAddress() {
var directive = {
restrict: 'EA',
scope: {
address: '='
},
bindToController: true,
templateUrl: 'modules/address/address.html',
controller: AddressController,
controllerAs: 'dir'
};
There you created an isolated scope, too, but this time you added the address
attribute to be passed in as an expression. So now the address
you passed in from the view in the second snippet will be available in the controller's scope. Setting bindToController: true
now, will bind all the current scope's properties to the controller (or more likely the controllerAs object). And now, it works as you would expect, because data will be passed in to the scope and data will be passed out to the controller's template scope.
在那里您也创建了一个独立的作用域,但这次您添加了address
要作为表达式传入的属性。所以现在address
你从第二个片段中的视图传入的将在控制器的范围内可用。bindToController: true
现在设置,会将所有当前范围的属性绑定到控制器(或者更有可能是 controllerAs 对象)。现在,它按您的预期工作,因为数据将传入作用域,而数据将传出到控制器的模板作用域。
Did that brief overview help you to better understand the concept of the scope
and bindToController
definition objects?
该简要概述是否有助于您更好地理解对象scope
和bindToController
定义对象的概念?