Angular компонентный подход и работа с разрешением в Router
Итак, я работаю с подходом на основе компонентов в angular, допустим, у меня есть директива, называемая <home></home>;
import template from './home.html';
import controller from './home.controller.js';
angular.module('myApp')
.directive('home', homeDirective);
let homeDirective = () => {
return {
restrict: 'E',
template,
controller,
controllerAs: 'vm',
bindToController: true
};
};
Теперь я могу использовать компонент <home></home>
в моей маршрутизации следующим образом:
angular.module('myApp')
.config(($routeProvider) => {
$routeProvider.when('/', {
template: '<home></home>'
})
})
Мне очень нравится этот подход, но с "старым" подходом я привык использовать "разрешение" в моем файле маршрутизации, чтобы отображать компонент только тогда, когда обещание было разрешено:
angular.module('myApp')
.config(($routeProvider) => {
$routeProvider.when('/', {
templateUrl: './home.html',
controller: './home.controller.js',
resolve: {
message: function(messageService){
return messageService.getMessage();
}
})
})
Вопрос
Как я могу использовать решение с помощью подхода, основанного на компонентах, в angular? ААЮ
Ответы
Ответ 1
Существует закрытый вопрос: параметр разрешения поддержки для директив.
Вывод состоит в том, что они не хотят, чтобы произвольные директивы загружались асинхронно, потому что это вызывало бы слишком много мерцания.
Хорошей новостью является то, что Angular 2 поддерживает это (и многое другое) на уровне DI таким образом, что он сплочен и не представляет тонны дополнительной сложности.
В Angular 1.x вы можете указать директиву с некоторой информацией, откуда должно быть получено сообщение, и обработать асинхронную загрузку в вашем контроллере. Таким образом вы также можете показать хороший экран загрузчика.
angular.module('myApp')
.config(($routeProvider) => {
$routeProvider.when('/', {
template: '<home my-datasource="feed1"></home>'
}).when('/other', {
template: '<home my-datasource="feed2"></home>'
})
})
.factory('DataSources', (messageService) => {
return {
feed1: messageService.getMessage,
feed2: messageService.getError
};
});
Или, если вы хотите, чтобы message
всегда был одним и тем же источником, вы можете записать messageService.getMessage().then(...)
в свой контроллер.
Если вы не хотите, чтобы директива была видимой вообще перед разрешением promises, вы можете ввести переменную области видимости, первоначально установленную в значение false, а затем установить ее значение true в разрешении, например:
app.controller('HomeController', ($scope, messageService) => {
$scope.loaded = false;
messageService.getMessage().then(message => {
...
$scope.loaded = true;
});
...
});
и скрыть директиву до загрузки ng-if="loaded"
в корневом элементе. Да, это слишком много кода пользователя, но вы, по крайней мере, контролируете все.
Ответ 2
Как оказалось, angular $routeProvider передает разрешенные локали на событие $routeChangeSuccess (nextRoute.locals). Таким образом, вы можете создать службу, которая прослушивает изменения маршрута и предоставляет локальные ресурсы:
angular.module('myApp', ['ngRoute'])
.factory('$routeLocals', function($rootScope) {
var locals = {};
$rootScope.$on('$routeChangeSuccess', function(_, newRoute) {
angular.copy(newRoute.locals, locals);
});
return locals;
})
.run(function($routeLocals) {});
Затем вы можете ввести $routeLocals в свою директиву и использовать их.
Пример: http://codepen.io/fbcouch/pen/eJYLBe
https://github.com/angular/angular.js/blob/master/src/ngRoute/route.js#L614
Ответ 3
В Angular 1.x, когда некоторые данные поступают в мои привязки к директиве ('=') из ajax и более того, я смотрю эти привязки в директиве, я не получил правильную директиву. Я проверяю множество тем stackoverflow и блоги, и все они пишут о привязках данных и просмотре, но это не помогает мне, я видел своими глазами, что когда-то директива не отображается, но данные приходят.
В этой ситуации помогает только resolve
в родительском контроллере директивы, потому что в других случаях он выглядит как поведение undefined. Я регистрируюсь из своей директивы, настройка данных нормально, но директива не отображается! (В простом случае я не использую ng-if или ng-show, чтобы скрыть ее).
Вы можете прочитать здесь