Сегодня разобрался с тем, что же такое директивы и как они работают в AngularJS. Учитывая, что не все статьи на хабре мне понятны, предприму собственную попытку донести свое открытие до масс.
Итак, что такое директива AngularJS?
В двух словах — это тег или атрибут тега в документе HTML, плюс немного магии.
Магия заключается в том, что директива может содержать в себе как шаблон отображения данных, так и контроллер для их обработки.
Рассмотрим пример — фрагмент из готового приложения.
<!-- Галерея картинок продукта -->
<div ng-controller="GalleryController as gallery" ng-show="product.images.length">
<div class="img-wrap">
<img ng-src="{{product.images[gallery.current]}}" />
</div>
<ul class="img-thumbnails clearfix">
<li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
<img ng-src="{{image}}" ng-click="gallery.setCurrent($index)"/>
</li>
</ul>
</div>
Сейчас мы увидим магию и наш пример превратится в лаконичное «ку»:
<!-- Галерея картинок продукта -->
<product-gallery></product-gallery>
Теперь разберемся, какие зелья нам нужно использовать, чтобы получилась такая красотища.
// Главный модуль приложения
(function(){
var app = angular('appName', []);
// Колдовство начинается!
// Название директивы автоматически преобразуется в строку типа camelCase
// Это значит, что вместо дефиса следующая буква становится заглавной
// Поэтому в HTML пишем тег "product-gallery", а в определении директивы "productGallery"
app.directive('productGallery', function() {
// По сути директива это лишь настройки отображения нашего нового тега
return {
restrict: 'E', // E - Element если определяем новый тег, и A - Attribute если новый атрибут
templateUrl: 'product-gallery.html', // указываем файл шаблона, который будет подставляться вместо тега директивы. Простые шаблоны можно указывать прямо здесь. Для этого потребуется свойство template вместо templateUrl
// теперь прикрепим к директиве собственный контроллер. Это оказывается очень просто
controller: function() {
this.current = 0;
this.setCurrent = function(imageNumber){
this.current = imageNumber || 0;
};
},
// И еще приятный сюрприз! Зададим контроллеру алиас - короткое имя
controllerAs: 'gallery'
};
});
})();
Вторым компонентом естественно будет сам шаблон. Как мы помним, это файл product-gallery.html:
<div ng-show="product.images.length">
<div class="img-wrap">
<img ng-src="{{product.images[gallery.current]}}" />
</div>
<ul class="img-thumbnails clearfix">
<li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
<img ng-src="{{image}}" ng-click="gallery.setCurrent($index)"/>
</li>
</ul>
</div>
Вау? Не знаю, как вам, а по мне так фантастика.
Соответственно после некоторых усилий приложение может принять вид:
<!-- Заголовок и цена -->
<product-title></product-title>
<!-- Описание и характеристики -->
<product-info></product-info>
<!-- Галерея картинок продукта -->
<product-gallery></product-gallery>
И все бы хорошо, но мучает вопрос — как быть с SEO? Но это вопрос уже другой статьи.
Всем хорошего дня!