带有角度指令的递归树没有范围隔离,强制您通过使用每个深度级别的不同范围属性来模拟隔离。
我没有找到,所以我自己写了。
假设您的 HTML 是:
<body ng-app="App" ng-controller="AppCtrl">
<div test="tree.children" test-label="tree.label">{{b}}</div>
</body>
然后你有一个主模块和一个控制器,将一棵树添加到范围:
var App = angular.module('App', []);
App.controller('AppCtrl', function($scope, $timeout) {
// prodive a simple tree
$scope.tree = {
label: 'A',
children: [
{
label: 'a',
children: [
{ label: '1' },
{ label: '2' }
]
},
{
label: 'b',
children: [
{ label: '1' },
{ label: '2' }
]
}
]
};
// test that pushing a child in the tree is ok
$timeout(function() {
$scope.tree.children[1].children.push({label: 'c'});
},2000);
$timeout(function() {
// test that changing a label is ok
$scope.tree.children[1].label = 'newLabel';
},4000);
});
最后考虑该指令的以下实现test
:
App.directive('test', function($compile) {
// use an int to suffix scope properties
// so that inheritance does not cause infinite loops anymore
var inc = 0;
return {
restrict: 'A',
compile: function(element, attr) {
// prepare property names
var prop = 'test'+(++inc),
childrenProp = 'children_'+prop,
labelProp = 'label'+prop,
childProp = 'child_'+prop;
return function(scope, element, attr) {
// create a child scope
var childScope = scope.$new();
function observeParams() {
// eval attributes in current scope
// and generate html depending on the type
var iTest = scope.$eval(attr.test),
iLabel = scope.$eval(attr.testLabel),
html = typeof iTest === 'object' ?
'<div>{{'+labelProp+'}}<ul><li ng-repeat="'+childProp+' in '+childrenProp+'"><div test="'+childProp+'.children" test-label="'+childProp+'.label">{{'+childProp+'}}</div></li></ul></div>'
: '<div>{{'+labelProp+'}}</div>';
// set scope values and references
childScope[childrenProp]= iTest;
childScope[labelProp]= iLabel;
// fill html
element.html(html);
// compile the new content againts child scope
$compile(element.contents())(childScope);
}
// set watchers
scope.$watch(attr.test, observeParams);
scope.$watch(attr.testLabel, observeParams);
};
}
};
});
所有的解释都在评论中。
你可以看看JSBin。
我的实现当然可以改进。