Если вы хотите следовать все «лучшие практики», есть несколько вещей, которые я рекомендовал бы, некоторые из которые затронуты в других ответах и комментариях к этому вопросу.
Во-первых, в то время как он не имеет слишком много аффекта на конкретный вопрос, который Вы задали, вы действительно упоминала эффективность, и лучший способ для обработки общих данных в вашем приложении к фактору это в оказание услуг.
Я лично рекомендовал бы охватить AngularJS promise system, что сделает ваши асинхронные службы более сложными по сравнению с необработанными обратными вызовами. К счастью, сервис Angular's $http
уже использует их под капотом. Вот сервис, который вернет обещание, которое решает данные из файла JSON; вызов службы более одного раза не вызовет второй HTTP-запрос.
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; вы должны указать , а не. В этом случае было бы заманчиво просто ввести в директиву службу locations
, но это сопрягает директиву с этой услугой.
Краткая информация о модульности кода: функции директивы должны почти никогда не отвечать за получение или форматирование собственных данных. Нет ничего, что помешало бы вам использовать службу $ http из директивы, но это почти всегда неправильно. Написание контроллера для использования $ http - это правильный способ сделать это. Директива уже касается элемента DOM, который является очень сложным объектом и его трудно вырезать для тестирования. Добавление сетевого ввода-вывода в микс делает ваш код намного сложнее для понимания и гораздо труднее проверить. Кроме того, сетевые операции ввода-вывода блокируются так, что ваша директива будет получать свои данные - возможно, в каком-то другом месте вы захотите, чтобы эта директива получала данные из сокета или принимала предварительно загруженные данные. Ваша директива должна либо принимать данные в качестве атрибута через область действия. $ Eval и/или иметь контроллер для обработки и хранения данных.
- The 80/20 Guide to Writing AngularJS Directives
В данном конкретном случае, вы должны поместить соответствующие данные на сферу вашего контроллера и делиться ею с директивой через атрибут.
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
директивы может использоваться с любым набором данных о местоположении - директива не жестко, чтобы использовать определенный набор данных, а просто связывая директиву, включив его в DOM, не будет удалять случайные HTTP-запросы.
Прежде всего, вы должны использовать службу вместо использования контроллера для получения данных о ваших местоположениях. После этого вы получаете зависимость от ваших данных с вашей службы как в контроллере, так и в вашей директиве. –