AngularJS : 带有 ng-repeat 和独立作用域的指令
AngularJS : directive with ng-repeat and isolated scope
我一直在尝试创建一个 指令,它获取元素的 内容并用 ng-repeat 包装它。诀窍是元素内容中的表达式必须与指令的隔离范围链接(所以我不能使用ng-transclude)。
我找到了一个看起来很完美的解决方案:
https://github.com/angular/angular.js/issues/7874#issuecomment-46410994
但它不适用于不令人满意的隔离范围,我需要一个隔离范围以避免污染父范围。
在下面的plnkr中,您可以尝试注释第10行,它会起作用。
http://plnkr.co/edit/B72H9Sd5Cs1Qc8GoTRGF
<test>
<h3>- number: {{item}}</h3>
</test>
app.directive('test', function(){
return {
restrict: 'E',
scope: {}, // try commenting this line
compile: function compile(tElement, tAttrs, tTransclude) {
var children = tElement.children();
var template = angular.element('<div ng-repeat="item in collection"></div>');
template.append(children);
tElement.html('');
tElement.append(template);
return function(scope, iElement, iAttrs, controller) {
scope.collection = [1, 2, 3, 4, 5];
};
}
};
});
我想要的是
- number: {{item}}
为每个集合项目重复,并且 {{item}} 表达式与孤立的链接范围。
我不明白这种行为。在我看来,{{item}} 表达式应该链接到指令的范围(通过 ng-repeat)。
相反,它与父范围链接。
有人可以帮我理解并解决这个问题吗?
谢谢。
好吧,试试 this fiddle 我添加了一些东西到:
app.directive('test', function(){
return {
restrict: 'E',
scope: {}, // try commenting this line
compile: function compile(tElement, tAttrs, tTransclude) {
var children = tElement.children();
var template = angular.element('<test2>{{collection}}<div ng-repeat="item in collection" ></div></test2>');
template.append(children);
tElement.html('');
tElement.append(template);
return function(scope, iElement, iAttrs, controller) {
scope.collection = [1, 2, 3, 4, 5];
console.log('test', scope);
};
}
};
});
app.directive('test2', function(){
return {
restrict: 'E',
scope: false,
link: function($scope) {
console.log('test2', $scope);
}
};
});
基本上,当您向 compile: function compile(tElement, tAttrs, tTransclude) {
中的 DOM 添加内容时,该代码会在链接阶段之前执行(return function(scope, iElement, iAttrs, controller) {
中的代码 运行。
如果您查看两个 console.log
调用,您会发现 test2
发生在 test
之前。
将其与 test
上的独立作用域相结合,最终 test
中的作用域成为 test2
中作用域的子级。违反直觉,我知道,但这是 AngularJS 的 compiling/linking 阶段的工作方式。
因此 collection
在 test2
中是 undefined
所以 ng-repeat
与 "repeat" 无关。
如果您删除 scope: {}
,您基本上是在告诉 test
的范围与 test2
的范围相同(它们是对同一对象的引用),因此 collection
将(最终)在所有指令中定义,包括 ng-repeat
.
我一直在尝试创建一个 指令,它获取元素的 内容并用 ng-repeat 包装它。诀窍是元素内容中的表达式必须与指令的隔离范围链接(所以我不能使用ng-transclude)。
我找到了一个看起来很完美的解决方案: https://github.com/angular/angular.js/issues/7874#issuecomment-46410994 但它不适用于不令人满意的隔离范围,我需要一个隔离范围以避免污染父范围。
在下面的plnkr中,您可以尝试注释第10行,它会起作用。 http://plnkr.co/edit/B72H9Sd5Cs1Qc8GoTRGF
<test>
<h3>- number: {{item}}</h3>
</test>
app.directive('test', function(){
return {
restrict: 'E',
scope: {}, // try commenting this line
compile: function compile(tElement, tAttrs, tTransclude) {
var children = tElement.children();
var template = angular.element('<div ng-repeat="item in collection"></div>');
template.append(children);
tElement.html('');
tElement.append(template);
return function(scope, iElement, iAttrs, controller) {
scope.collection = [1, 2, 3, 4, 5];
};
}
};
});
我想要的是
- number: {{item}}
为每个集合项目重复,并且 {{item}} 表达式与孤立的链接范围。我不明白这种行为。在我看来,{{item}} 表达式应该链接到指令的范围(通过 ng-repeat)。 相反,它与父范围链接。
有人可以帮我理解并解决这个问题吗?
谢谢。
好吧,试试 this fiddle 我添加了一些东西到:
app.directive('test', function(){
return {
restrict: 'E',
scope: {}, // try commenting this line
compile: function compile(tElement, tAttrs, tTransclude) {
var children = tElement.children();
var template = angular.element('<test2>{{collection}}<div ng-repeat="item in collection" ></div></test2>');
template.append(children);
tElement.html('');
tElement.append(template);
return function(scope, iElement, iAttrs, controller) {
scope.collection = [1, 2, 3, 4, 5];
console.log('test', scope);
};
}
};
});
app.directive('test2', function(){
return {
restrict: 'E',
scope: false,
link: function($scope) {
console.log('test2', $scope);
}
};
});
基本上,当您向 compile: function compile(tElement, tAttrs, tTransclude) {
中的 DOM 添加内容时,该代码会在链接阶段之前执行(return function(scope, iElement, iAttrs, controller) {
中的代码 运行。
如果您查看两个 console.log
调用,您会发现 test2
发生在 test
之前。
将其与 test
上的独立作用域相结合,最终 test
中的作用域成为 test2
中作用域的子级。违反直觉,我知道,但这是 AngularJS 的 compiling/linking 阶段的工作方式。
因此 collection
在 test2
中是 undefined
所以 ng-repeat
与 "repeat" 无关。
如果您删除 scope: {}
,您基本上是在告诉 test
的范围与 test2
的范围相同(它们是对同一对象的引用),因此 collection
将(最终)在所有指令中定义,包括 ng-repeat
.