我的首选答案是“不要这样做”,但如果做不到这一点,因为这很有趣,这里有一个概念证明,由 this question 协助,主要改编自 this blog post:
app.directive('myRepeat', function(){
return {
transclude : 'element',
compile : function(element, attrs, linker){
return function($scope, $element, $attr){
var collectionExpr = attrs.myRepeat;
var parent = $element.parent();
var elements = [];
// $watchCollection is called everytime the collection is modified
$scope.$watchCollection(collectionExpr, function(collection) {
var i, block, childScope;
// check if elements have already been rendered
if(elements.length > 0){
// if so remove them from DOM, and destroy their scope
for (i = 0; i < elements.length; i++) {
elements[i].el.remove();
elements[i].scope.$destroy();
};
elements = [];
}
for (i = 0; i < collection.length; i++) {
// create a new scope for every element in the collection.
childScope = $scope.$new();
// ***
// This is the bit that makes it behave like a `with`
// statement -- we assign the item's attributes to the
// child scope one by one, rather than simply adding
// the item itself.
angular.forEach(collection[i], function(v, k) {
childScope[k] = v;
});
// ***
linker(childScope, function(clone){
// clone the transcluded element, passing in the new scope.
parent.append(clone); // add to DOM
block = {};
block.el = clone;
block.scope = childScope;
elements.push(block);
});
};
});
}
}
}
});
然后这会做你想做的事:
app.controller("myController", function($scope, $http) {
$scope.items = [
{a: 123, b: 234},
{a: 321, b: 432}
];
});
使用你想要的 HTML 结构:
<div ng-controller="myController">
<ul>
<li my-repeat="items">
{{ a }} {{ b }}
</li>
</ul>
</div>
请注意,鉴于属性被复制到子作用域中,而不是被引用,如果对视图进行更改,它们不会影响模型(即父 items 列表),严重限制了该指令。你可以用一个额外的scope.$watch 来解决这个问题,但使用ng-repeat 几乎肯定不会像通常使用的那样大惊小怪。