If you want to follow all the "best practices," there's a few things I'd recommend, some of which are touched on in other answers and comments to this question.
首先,虽然它对您提出的特定问题没有太大影响,但您确实提到了效率,在应用程序中处理共享数据的最佳方法是将其分解到服务中.
I would personally recommend embracing AngularJS's promise system, which will make your asynchronous services more composable compared to raw callbacks. Luckily, Angular's $http
service already uses them under the hood. Here's a service that will return a promise that resolves to the data from the JSON file; calling the service more than once will not cause a second HTTP request.
app.factory('locations', function($http) {
var promise = null;
return function() {
if (promise) {
// If we've already asked for this data once,
// return the promise that already exists.
return promise;
} else {
promise = $http.get('locations/locations.json');
return promise;
}
};
});
就将数据放入指令而言,重要的是要记住,指令是为抽象通用DOM操作而设计的;您应该用特定于应用程序的服务将它们注入not.在本例中,简单地将locations
服务注入到指令中是很有诱惑力的,但是这会将指令耦合到该服务.
A brief aside on code modularity: a directive’s functions should almost never be responsible for getting or formatting their own data. There’s nothing to stop you from using the $http service from within a directive, but this is almost always the wrong thing to do. Writing a controller to use $http is the right way to do it. A directive already touches a DOM element, which is a very complex object and is difficult to stub out for testing. Adding network I/O to the mix makes your code that much more difficult to understand and that much more difficult to test. In addition, network I/O locks in the way that your directive will get its data – maybe in some other place you’ll want to have this directive receive data from a socket or take in preloaded data. Your directive should either take data in as an attribute through scope.$eval and/or have a controller to handle acquiring and storing the data.
- The 80/20 Guide to Writing AngularJS Directives
In this specific case, you should place the appropriate data on your controller's scope and share it with the directive via an attribute.
app.controller('SomeController', function($scope, locations) {
locations().success(function(data) {
$scope.locations = data;
});
});
<ul class="list">
<li ng-repeat="location in locations">
<a href="#">{{location.id}}. {{location.name}}</a>
</li>
</ul>
<map locations='locations'></map>
app.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
scope: {
// creates a scope variable in your directive
// called `locations` bound to whatever was passed
// in via the `locations` attribute in the DOM
locations: '=locations'
},
link: function(scope, element, attrs) {
scope.$watch('locations', function(locations) {
angular.forEach(locations, function(location, key) {
// do something
});
});
}
};
});
通过这种方式,map
指令可以与any组位置数据一起使用——该指令没有硬编码以使用特定的数据集,并且简单地通过将其包含在DOM中来链接该指令不会触发随机HTTP请求.