我有两个简单的指令,它们在DOM中生成类似的元素。
为什么不在隔离范围内触发方法?
这是Plunk
的Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.alertMessage = function(){
alert('I live in mainController');
}
});
app.directive('isolated', function(){
return {
scope: {},
link: function(scope, element, attrs) {
scope.alertMessage = function(){
alert('I live in the isolated directive');
};
}
};
});
app.directive('isolatedWithTemplate', function(){
return {
scope: {},
replace: true,
template: '<button ng-click="alertMessage()">Press me</button>',
link: function(scope, element, attrs) {
scope.alertMessage = function(){
alert('I live in the isolated directive');
};
}
};
});
HTML
<button isolated ng-click="alertMessage()">Press me</button>
<div isolated-with-template></div>
答案 0 :(得分:1)
<button isolated ng-click="alertMessage()">Press me</button>
在这种情况下,ng-click
独立于隔离指令,即使将html更改为
<button ng-click="alertMessage()">Press me</button>
所以上面的ng-click
不适用于isolate指令,而是适用于控制器的范围......
ng-click
的{{1}}正在指令范围内工作..
答案 1 :(得分:1)
(答案更新了@Edminsson指出的更正信息)
请参阅以下链接以了解范围 - 虽然链接不解释上述行为,但我的答案将尝试解释。
下面将尝试解释为什么元素与'隔离'&#39;指令说&#39;我在mainController范围内&#39;而不是&#39;我在孤立的范围内。
注意两个DOM元素的顺序无关紧要,优先级对我们看到的内容都没有影响。
<div isolated-with-template></div>
<button isolated ng-click="alertMessage()">No Template</button>
元素上的每个指令都是在父级的范围内编译的。 这意味着ng-click绑定到MainController中的scope函数。 isolate指令确实创建了一个新的隔离范围及其上的函数,但是ng-click已经绑定到mainController的函数对象$ scope.alertMessage()。
带有isolated-with-template的元素也会使用父作用域进行编译。但是当它遇到指令时它现在有一个模板。这被编译(确切地说是nodeLinkFn。有afterTemplateNodeLinkFn所以带有模板或templateUrls的指令将使用它)。此时,隔离范围具有来自隔离范围的函数alertMessage。还要知道MainController的alertMessage已经在所有这些之前在该范围上定义。
1)Angular首先处理DOM深度并向后链接
2)模板的根获得其直接范围
3)当多个指令在元素上请求范围时,只能获得一个范围
scope = true会怎样?
在this plnkr中,您会注意到该指令不再说“我在主控制器中”。
scope:true,
您实际上正在获得全新的儿童范围。当创建链接功能时,角度知道这个范围是一个全新的范围。
隔离范围的一个技巧 尝试分配模板:&#39; &#39;,并替换:true 并且你有自己独立的范围。
Isolated scope trick using another example
.directive("client", function() {
return {
restrict: "A",
template: ' ',//notice extra spaces
replace: true,//notice this
scope: {
name: "@name",
client: "=client"
}
};
});