Автор оригинала: Justin Obney.
Универсальный угла был одним из величайших повышений производительности для быстрого развития приложений в моей карьере. Однако некоторые из общих стратегий, реализованных на мой взгляд, могут быть улучшены на мой взгляд.
В Angularjs существует множество важно для разделения опасений. Одним из наиболее практичных узоров для проведения состояния приложения является перемещение этих данных в угловые услуги или фабрики. Какой из первых для использования является совершенно личным предпочтением, на мой взгляд (я выбираю за фабрики большую часть времени).
Целью данного поста направлена на услуги, которые проводят коллекции, которые обновляют от удаленных вызовов данных.
Целевая версия Angularjs во время написания: 1.2.19
Слишком много раз, я бежал через угловые контроллеры, приносящие $ Scope
Сервис только к $ смотреть
Сборная службы:
Плохо:
app.controller('Ctrl1', function($scope, DataFactory) { // bind the controller property to the service collection this.items = DataFactory.items; // watch the collection for changes $scope.$watch(watchSource, function(current, previous){ this.items = current; }); function watchSource(){ return DataFactory.items; } }); app.factory('DataFactory', function($q, $timeout) { var svc = {}; svc.items = []; svc.getDataStream = function() { var fakeData = [ { id: 1, name: 'name 1' }, { id: 2, name: 'name 2' }, { id: 4, name: 'name 4' } ]; // using $q to fake async data grab return $q.when(fakeData) .then(function(data) { svc.items = data; }); }; return svc; });
Я знаю, что вы думаете: «Почему это просто не работает по умолчанию?» Мы явно обновляем Datafactory.items
Отказ
svc.getDataStream = function() { return $q.when(fakeData) .then(function(data) { // here we are clearly reseting the data // to the response of the call.. Why doesn't // it just databind? svc.items = data; }); };
Причина, по которой угловые не «смотрит» это значение, это потому, что когда он устанавливает неявную $ смотреть
С точки зрения, он ссылается на оригинальный массив из Datafactory
Отказ Но когда данные возвращаются через $ http
он заменяет свойство с другой справочностью на массиве. Таким образом, угловой не может посмотреть коллекцию без добавления противных $ смотреть
Функции в ваших контроллерах.
Так почему же $ Watch. Плохая вещь в контроллере?
Он добавляет к познавательной нагрузке, необходимой для понимания того, что происходит в контроллере. Когда мы смотрим на код, что другие (или самые 6 месяцев) писали, возможность легко понять что не тратя много времени, разборки Как очень выгодно Любые привязки в вашем представлении вызывают неявные часы для установки. Также все $ смотреть
Функции выполняются для каждого $ digest
что может произойти много раз в «диватовом цикле» (угловые пинает их с большинством взаимодействий). Добавление еще одного часа – это шаблон, который может привести вас к проблемам производительности в будущем.
Конечно, мы можем удалить зависимость на $ Scope
Просто чтобы посмотреть эту коллекцию. Давайте посмотрим на очень простой пример этого разделения, адаптированные из Девиз Тоддо Отказ
Лучшее:
app.controller('Ctrl1', function(DataFactory) { // bind the controller property to the service collection this.items = DataFactory.items; // invoke the call to get data DataFactory .getDataStream() .then(function() { // update the controller collection property this.items = DataFactory.items; }.bind(this)); }); // sample "service" for getting data app.factory('DataFactory', function($q, $timeout) { var svc = {}; svc.items = []; svc.getDataStream = function() { var fakeData = [ { id: 1, name: 'name 1' }, { id: 2, name: 'name 2' }, { id: 4, name: 'name 4' } ]; // using $q to fake async data grab return $q.when(fakeData) .then(function(data) { svc.items = data; }); }; return svc; });
Теперь я не ненавижу этот формат. Вот после каждого вызова обновления источника данных обслуживания, как обновляется как ссылка на источник, так и контроллер. Работает для того, что он предназначен, и это довольно легко понять, что происходит. Тем не менее, это на самом деле не устраняет контроллеры, кроме одного, вызывающих обновленную услугу.
Как насчет этого:
app.controller('Ctrl1', function(DataFactory) { // bind the controller property to the service collection this.items = DataFactory.items; // but wouldn't it be so much better // to just call it and let it work DataFactory.getDataStream(); });
Разве это просто читает так много чище?
Введите angular.Copy
Отказ Что angular.Copy
Предполагается, что при задании нового массива и массив источника пустое источника (настроив длину до 0
Я думаю, что …), а затем вытесните массив с новыми элементами массива.
Наш конечный результат:
var app = angular.module('app', []); app.controller('Ctrl1', function(DataFactory) { this.items = DataFactory.items; DataFactory.getDataStream(); }); app.controller('Ctrl2', function($timeout, DataFactory) { // when this eventually fires and gets *remote* data again // our other controller will automatically sync up // without the need for the $watch function $timeout(DataFactory.getDataStream, 2000); }); app.factory('DataFactory', function($q) { var svc = {}; svc.items = []; svc.getDataStream = function() { var fakeData = [ { id: 1, name: 'name 1' }, { id: 2, name: 'name 2' }, { id: 4, name: 'name 4' } ]; // using $q to fake async data grab return $q.when(fakeData) .then(function(data) { // this is the magic angular.copy(data, svc.items); }); }; return svc; });
Эта статья была первоначально опубликована на мой блог .