=====от directive() к component()=====
В Angular 1.5 нам был представлен новый метод .component(), который намного проще чем .directive() и при этом он использует все лучшее по умолчанию. Метод .component() также позволит разработчикам писать в Angular2 стиле, то есть сделает переход на вторую версию максимально безболезненным.\\
\\
В этом посте мы попробуем параллельно разобрать старый и новый подходы для создания компонентов.\\
\\
На примере простой директивы counter мы посмотрим как можно создать компонент с аналогичной функциональностью:\\
контроллер
{{count}}
====Объект вместо Функции====
Начнем наш анализ со способа задания и обратим внимание на то, что параметры в компонент передаются как объект (а не функция, что было в директиве):\\
\\
// до
.directive('counter', function counter() {
return {
};
});
// после
.component('counter', {
});
====Scope и BindToController становятся просто Bindings====
В директиве мы можем задавать **scope** 3-мя способами: родительский(скоуп не создается), наследник от родительского, изолированный. Со временем мы приходим к выводу, что изолированный скоуп, где мы четко задаем входящие параметры, наилучший вариант. Так же каждый раз для изолированного скоупа нам приходиться прописывать **bindToController**, чтобы прокинуть данные со скоупа непосредственно на контроллер директивы.\\
\\
Свойство компонента **bindings** позволяет использовать 2 в одном, так как компонент использует изолированный скоуп по умолчанию:\\
\\
// before
.directive('counter', function counter() {
return {
scope: {},
bindToController: {
count: '='
}
};
});
// after
.component('counter', {
bindings: {
count: '='
}
});
====Controller и ControllerAs====
Ничего не изменилось в способе задания контроллера, однако теперь **controllerAs** параметр по умолчанию, который задан как **“$ctrl“**: то есть если мы в контроллере напишем:
this.x = 5;
то в шаблоне компонента потом можно будет обратиться вот так:\\
{{$ctrl.x}}
Итак, что у нас получилось с контроллером для обоих случаев:\\
\\
**до**
контроллер
{{count}}
**после**
контроллер
{{count}}
Я очень упростил для понимания пункт из статьи, поэтому рекомендую также заглянуть в оригинал.\\
\\
====Шаблоны====
В определении шаблонов есть небольшое различие: шаблон компонента может задаваться как функция, в которую инжектятся элемент и атрибуты:\\
{
...
template: function ($element, $attrs) {
// access to $element and $attrs
return '...';
}
...
}
====Улучшенное require====
Да, это свершилось! Теперь мы можем задать имя для контроллера, подключаемого к нашему компоненту, и обратиться к нему из контроллера( до этого только из метода link, а в контроллер оно попадало только [[https://github.com/angular/angular.js/issues/5893|путем ужасных костылей]]):\\
\\
{
...
require: {
parent: '^parentComponent'
},
controller: function () {
// use this.parent to access required Objects
this.parent.foo();
}
...
}
В данном случае мы определили подключаемый контроллер на свойстве **parent**.
====Одностороннее связывание====
Еще одна фишка компонентов и Angular1.5 это одностороннее связывание, которое определяется следующим синтаксисом:\\
{
...
bindings: {
oneWay: '<',
twoWay: '='
},
...
}
если мы задали свойство oneWay таким образом, то оно будет реагировать на изменения внешнего связанного объекта, при этом свои изменения передавать “наружу” не будет. И да, сразу отвечу на вопрос, который у вас наверное появился: работает только в одну сторону.
====Нет никакого нового концепта====
Если вы посмотрите на исходный код, то увидите что разработчики AngularJS особо не парились и сделали метод **component()** просто оболочкой над directive().