AngularJS - 带 ng-transclude 的指令,无双向绑定
AngularJS - directive with ng-transclude, no two-way binding
看到DEMO
<body ng-controller="MainCtrl">
{{ obj }}
<dir>
<input type="text" ng-model="obj" />
</dir>
</body>
为什么当我使用 ng-transclude
更改自定义指令中的 obj
范围变量时,我没有在 MainCtrl
$scope.obj
.[=21= 中更改它]
但是当我在 MainCtrl
中有 $scope.obj = { name : 'test' };
时,双向绑定按我预期的方式工作。
查看工作DEMO
<body ng-controller="MainCtrl">
{{ obj.name }}
<dir>
<input type="text" ng-model="obj.name" />
</dir>
</body>
这种行为的解释是什么?
从子作用域访问父作用域上的原始变量时出现问题。您有一个子作用域,因为 transclude: true
创建了一个新作用域。
您真的应该阅读 this article 以深入了解正在发生的事情。
文章要点:
Scope inheritance is normally straightforward, and you often don't
even need to know it is happening... until you try 2-way data binding
(i.e., form elements, ng-model) to a primitive (e.g., number, string,
boolean) defined on the parent scope from inside the child scope.
和
This issue with primitives can be easily avoided by following the
"best practice" of always have a '.' in your ng-models.
发生的事情是在涉及基元时没有咨询父范围。这是 Javascript 的事情,甚至 Angular 的都不是。
我还创建了一个 Demo 隐藏在子作用域中的对象。 (阴影非原始对象):
app.directive('dir', function () {
return {
restrict: 'E',
scope: true,
template: "<div><input type=\"text\" ng-model=\"obj.name\" /></div>",
link: function(scope, element, attrs) {
scope.obj = {name : "newname"};
}
};
});
被嵌入的 html 生成一个 MainCtrl
的子作用域,当写入这个新的 属性 (obj
) 时,子作用域生成一个覆盖父作用域的新作用域.
The prototype chain is not consulted, and a new aString property is added to the childScope. This new property hides/shadows the parentScope property with the same name.
修改后的版本有效,因为子作用域(嵌入)首先访问 obj(引用),然后访问 属性 名称
在 https://github.com/angular/angular.js/wiki/Understanding-Scopes
了解有关作用域继承的更多信息
以及 http://angular-tips.com/blog/2014/03/transclusion-and-scopes/
处的包含和作用域行为
当您从同一范围查询 obj
的值时,这有效 - 指令的范围:
<body ng-controller="MainCtrl">
{{ obj }}
<dir>
<p>
The following text will be synched with the model:
</p>
<span>{{ obj }}</span>
<br/>
<input type="text" ng-model='obj' />
</dir>
</body>
看到DEMO
<body ng-controller="MainCtrl">
{{ obj }}
<dir>
<input type="text" ng-model="obj" />
</dir>
</body>
为什么当我使用 ng-transclude
更改自定义指令中的 obj
范围变量时,我没有在 MainCtrl
$scope.obj
.[=21= 中更改它]
但是当我在 MainCtrl
中有 $scope.obj = { name : 'test' };
时,双向绑定按我预期的方式工作。
查看工作DEMO
<body ng-controller="MainCtrl">
{{ obj.name }}
<dir>
<input type="text" ng-model="obj.name" />
</dir>
</body>
这种行为的解释是什么?
从子作用域访问父作用域上的原始变量时出现问题。您有一个子作用域,因为 transclude: true
创建了一个新作用域。
您真的应该阅读 this article 以深入了解正在发生的事情。
文章要点:
Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope.
和
This issue with primitives can be easily avoided by following the "best practice" of always have a '.' in your ng-models.
发生的事情是在涉及基元时没有咨询父范围。这是 Javascript 的事情,甚至 Angular 的都不是。
我还创建了一个 Demo 隐藏在子作用域中的对象。 (阴影非原始对象):
app.directive('dir', function () {
return {
restrict: 'E',
scope: true,
template: "<div><input type=\"text\" ng-model=\"obj.name\" /></div>",
link: function(scope, element, attrs) {
scope.obj = {name : "newname"};
}
};
});
被嵌入的 html 生成一个 MainCtrl
的子作用域,当写入这个新的 属性 (obj
) 时,子作用域生成一个覆盖父作用域的新作用域.
The prototype chain is not consulted, and a new aString property is added to the childScope. This new property hides/shadows the parentScope property with the same name.
修改后的版本有效,因为子作用域(嵌入)首先访问 obj(引用),然后访问 属性 名称
在 https://github.com/angular/angular.js/wiki/Understanding-Scopes
了解有关作用域继承的更多信息以及 http://angular-tips.com/blog/2014/03/transclusion-and-scopes/
处的包含和作用域行为当您从同一范围查询 obj
的值时,这有效 - 指令的范围:
<body ng-controller="MainCtrl">
{{ obj }}
<dir>
<p>
The following text will be synched with the model:
</p>
<span>{{ obj }}</span>
<br/>
<input type="text" ng-model='obj' />
</dir>
</body>