
Всем привет. Сегодня мы с вами разберем, что такое controller as синтаксис и почему scope это плохо.
Давайте создадим пример, который немного будет напоминать пример из предыдущего урока.
<div ng-controller="mainCtrl">
<div ng-controller="firstCtrl">
<div ng-controller="secondCtrl">
{{myLesson}}
</div>
</div>
</div>
Создадим контроллер mainCtrl. Вложим в него контроллер firstCtrl, а в него secondCtrl. Внутри выведем переменную myLesson.
Теперь опишем под них контроллеры.
var app = angular.module('app', []);
app.controller('mainCtrl', function ($scope) {
});
app.controller('firstCtrl', function ($scope) {
});
app.controller('secondCtrl', function ($scope) {
});
У нас сейчас достаточно стандартный пример с вложенными контроллерами. Теперь в $scope запишем переменную myLesson
var app = angular.module('app', []);
app.controller('mainCtrl', function ($scope) {
});
app.controller('firstCtrl', function ($scope) {
});
app.controller('secondCtrl', function ($scope) {
$scope.myLesson = 'Lesson';
});
Если мы посмотрим в браузер, то у нас вывелась строка Lesson. Что будет, если мы перенесем этот код в firstCtrl?
var app = angular.module('app', []);
app.controller('mainCtrl', function ($scope) {
});
app.controller('firstCtrl', function ($scope) {
$scope.myLesson = 'Lesson';
});
app.controller('secondCtrl', function ($scope) {
});
Все точно так же будет работать, даже, если мы его перенесем в mainCtrl. Это конечно хорошо, но у нас появилось усложнение кода, потому что мы не знаем, из какого конкретно контроллера этот код будет вызван и где находится эта переменная - в secondCtrl, firstCtrl или mainCtrl. Из-за этого код становится более сложным.
Чтобы этого избежать, используется controller as синтаксис.
<div ng-controller="mainCtrl as mainCtrl">
<div ng-controller="firstCtrl as firstCtrl">
<div ng-controller="secondCtrl as secondCtrl">
{{myLesson}}
</div>
</div>
</div>
Что это значит? Это значит, что в шаблоне у нас теперь появляется переменная mainCtrl, firstCtrl и secondCtrl, которые связаны с this внутри каждого контроллера. Давайте попробуем. Во-первых, удаляем $scope во всех трех контроллерах.
var app = angular.module('app', []);
app.controller('mainCtrl', function () {
});
app.controller('firstCtrl', function () {
});
app.controller('secondCtrl', function () {
});
Теперь мы можем использовать this, вместо того, чтобы использовать $scope.
app.controller('secondCtrl', function () {
this.myLesson = 'Lesson';
});
Сейчас, если мы обновим страницу, то у нас ничего не выведется, потому что myLesson переменной уже не существует. Теперь в шаблоне мы можем к ней достучаться только с помощью переменной secondCtrl.
<div ng-controller="mainCtrl as mainCtrl">
<div ng-controller="firstCtrl as firstCtrl">
<div ng-controller="secondCtrl as secondCtrl">
{{secondCtrl.myLesson}}
</div>
</div>
</div>
secondCtrl здесь именно та переменная, которую мы обьявили в secondCtrl as secondCtrl. Мы могли назвать ее в выражении
secondCtrl as secondCtrl
как угодно. Как мы видим Lesson выводится в браузере. Теперь у нас нет проблем с пониманием из какого контроллера вызвалась переменная. Она не может находиться ни в firstCtrl, ни в mainCtrl.
Давайте скопируем этот код в другие контроллеры
var app = angular.module('app', []);
app.controller('mainCtrl', function () {
this.myLesson = 'MainLesson';
});
app.controller('firstCtrl', function () {
this.myLesson = 'FirstLesson';
});
app.controller('secondCtrl', function () {
this.myLesson = 'SecondLesson';
});
Если мы хотим вывести myLesson из firstCtrl, то мы должны написать
{{firstCtrl.myLesson}}
Если же мы хотим вывести переменную из mainCtrl, то тогда пишем
{{mainCtrl.myLesson}}
Как мы видим, весь синтаксис, который нам нужно написать для того, чтобы controller as синтаксис работал это
имя-контроллер as имя-которые-мы-хотим-использовать
и в контроллере использовать this. В этом случае мы можем не использовать $scope вообще.
Давайте попробуем добавить какую-нибудь функцию, чтобы было видно как это выглядит.
<div ng-controller="mainCtrl as mainCtrl">
<div ng-controller="firstCtrl as firstCtrl">
<div ng-controller="secondCtrl as secondCtrl">
{{secondCtrl.myLesson}}
<button ng-click='mainCtrl.addLesson()'>Add lesson</button>
</div>
</div>
</div>
Функция addLesson не может быть написана в шаблоне без переменной контроллера. Тогда ангулар будет ожидать, что в mainCtrl у нас есть метод addLesson
app.controller('mainCtrl', function () {
this.myLesson = 'MainLesson';
this.addLesson = function () {
console.log('addLesson');
}
});
Как мы видим, в браузере кнопка Add lesson работает и выводит сообщение в консоль.
Я во всех своих проектах применяю только controller as синтаксис, а $scope стараюсь использовать как можно реже.
Теперь давайте посмотрим как ангулар обрабатывает controller as синтаксис внутри себя. Давайте на примере mainCtrl заинджектим $scope и в конце контроллера в переменную this.mainCtrl запишем this.
app.controller('mainCtrl', function ($scope) {
this.myLesson = 'MainLesson';
this.addLesson = function () {
console.log('addLesson');
}
$scope.mainCtrl = this;
});
Что это дает? Мы создали переменную mainCtrl, которая будет доступна в шаблоне. Если мы сейчас уберем controller as синтаксис для mainCtrl, то код продолжит работать без изменений, так как переменная mainCtrl у нас уже есть.
<div ng-controller="mainCtrl">
<div ng-controller="firstCtrl as firstCtrl">
<div ng-controller="secondCtrl as secondCtrl">
{{mainCtrl.myLesson}}
<button ng-click='mainCtrl.addLesson()'>Add lesson</button>
</div>
</div>
</div>
Только что мы с вами реализовали свой controller as синтаксис. Конечно лучше не использовать наш вариант, а использовать нативные методы ангулара так как это проще.