От автора: в этом уроке мы изучим основы AngularJS, и на простых примерах AngularJS раскроем мощь двусторонней привязки данных, а также архитектуру AngularJS в целом, как фреймворка. Примеры AngularJS из данной статьи Вы вполне можете использовать на практике.
Введение
AngularJS — что это? AngularJS это монстр среди JS фреймворков, с помощью огромного набора инструментов можно создавать действительно мощные, простые в обслуживании и структурированные приложения. Данный фреймворк существенно облегчает разработку динамических приложений, благодаря своему синтаксису, простой визуальной манипуляции объектами, а также двусторонней привязке данных. Сегодня мы с вами с головой погрузимся в самые основы Angular и продемонстрируем легкость и мощь фреймворка.
Перед тем, как продолжить, необходимо ознакомиться с терминологией. Выше я уже упоминал «двустороннюю привязку данных», а что это вообще значит? Привязка данных означает связь между моделью (бизнес модель) и видом (UI), и при изменении одного, изменяется и второе. В Angular данные связаны между собой в обоих направлениях. Это значит, если в базе данных что-то обновилось, то вид автоматически обновится для отображения новых данных, и наоборот. При таком подходе манипуляция DOM’ом страницы становится очень простой, а еще это и есть одна из особенностей, почему многие используют Angular.
Angular также применяет контроллеры, принцип действия которых схож с ссылками на виды. Из-за двусторонней привязки данных в Angular очень легко создавать и поддерживать контроллеры, что в итоге очищает код и делает его читаемым. Можно в любой момент получить данные из DOM и отослать их обратно. Также привязка данных делает ненужным большое количество кода, связанного с манипуляцией DOM в JS, еще больше очищая код и придавая модульность контроллерам.
Последний термин и самый главный – «директивы». Директивы помогают структурировать повторно используемые компоненты при помощи ваших собственных имен. В этом уроке мы не будем показывать, как создать свои собственные директивы. Но я все же приведу парочку из них, так как в Angular есть встроенные директивы. Обычно, они начинаются с ng и очень полезны. Без лишних слов, давайте делать красиво.
Автозагрузка приложения
Для загрузки любого Angular приложения необходимо вызвать директиву ng-app. Эту директиву можно прописать в любом HTML теге, она используется для автозагрузки приложений Angular. Ng-app представляет из себя корень Angular приложения, и на одной веб-странице может быть запущено только одно Angular приложение. В основном почти всегда вызов директивы можно встретить в теге html:
1 2 |
<html ng-app="app"> </html> |
Заметьте, что мы дали нашему приложению имя app. Посмотрим, как оно себя поведет, добавим немного JS кода. Но перед тем как продолжить необходимо подключить саму библиотеку Angular, а наш код будет находиться в файле app.js. Для добавления Angular в наш проект я использовал менеджер Bower, я настроил его сохранять свои компоненты в папку /lib. Файл app.js я сохранил в папке /app. Наш файл index.html выглядит так:
1 2 3 4 5 6 7 8 9 10 11 |
<!DOCTYPE html> <html lang="en" ng-app="app"> <head> <script src="lib/angular/angular.min.js"></script> </head> <body> <script src="app/app.js"></script> </body> </html> |
Далее мы будем работать в файле app.js. Чтобы Angular понял, что мы готовы с ним работать, необходимо задать первоначальное состояние приложения. Ниже код JS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
(function() { 'use strict'; /** * angular * Description: Angular! */ angular /** * app * Description: Устанавливаем первоначальное состояние приложения */ .module('app', []) })(); |
Код выше можно разбить на 3 части:
Запрет на автоматически запускаемые функции, защищает от захламления глобального пространства переменных.
Объявление Angular
.module(‘app’, []) – устанавливает первоначальное состояние приложения и задает ему имя app
Если интересно, то квадратные скобки в установщике отвечают за загрузку любых зависимостей, которые нам могут понадобиться в шаблоне внедрения зависимостей. В этом уроке мы не будем рассказывать про внедрение зависимостей, но, если вы будете дальше изучать Angular, то это одна из важнейших тем, так что вам нужно с ней ознакомиться самостоятельно! Сейчас наше приложение не делает абсолютно ничего, давайте создадим и добавим первый контроллер и как-нибудь привяжем его к DOM.
Создание первого контроллера
Для объявления нового контроллера в Angular, мы просто прикрепляем строку .controller к нашему модулю (конструктор контроллера). В нашем случае, так как мы пишем весь JS код в одном файле, мы можем просто дописать так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
(function() { 'use strict'; angular .module('app', []) /** * AppController * Description: Sets up a controller */ .controller('AppController', ['$scope', function($scope) { }]); })(); |
Стоит обратить внимание на пару вещей. Первое – мы назвали наш контроллер AppController, похожим образом мы назвали наш базовый модуль. Второе – мы использовали строчное подключение, чтобы явно дать понять, что переменная $scope это зависимость от нашего контроллера. И третье, на вход безымянной функции подается переменная $scope, т.е. мы делаем эту переменную доступной внутри функции, а т.е. и для всего контроллера. А что это вообще за переменная $scope?
В Angular scope это объект, связанный с моделью приложения, и работает, как связующее звено между контроллером и видом. Первоначальное состояние scope можно задать, прицепив к объекту различные свойства. Также к объекту $scope можно цеплять методы. Все свойства объекта $scope будут доступны в DOM на уровне объявления контроллера. Но как же объявить сам контроллер?
В html коде нам нужен какой-то раздел DOM, который будет связан с контроллером таким образом, чтобы мы действительно могли применить двустороннюю привязку данных и, наконец, начать работать с Angular. Напомним, что наш контроллер называется AppController, так что объявить контроллер в HTML можно так:
1 2 |
<main ng-controller="AppController"> </main> |
Сейчас мы использовали уже вторую директиву, ng-controller. Теперь наш AppController связан с DOM. Теперь мы полностью готовы! Посмотрим на парочку основных возможностей Angular в действии. Весь код, будем считать, будет внутри функции контроллера.
Рекомендуется использовать в имени контроллера слово controller, чтобы было четко ясно, к какому контроллеру вы обращаетесь в текущем шаблоне. В этом уроке мы так и поступим.
Очень простая двусторонняя привязка данных
В нашем HTML вывод свойств можно делать с помощью двух скобок:
1 |
<p>Hello, <em>{{ username }}</em>!</p> |
Как можно заметить, на экране переменная usename ничего не отобразит, так как username не добавлена в пространство переменных:
1 2 3 4 5 |
/** * username * Description: The default username to attach to the scope */ $scope.username = 'Nick'; |
Обновите страницу и вуаля! Только что вы стали свидетелем двусторонней привязки данных в нашем приложении. Пойдем еще дальше, посмотрим, сможем ли мы изменить имя по клику.
Изменение значения свойств с помощью ng-click
В Angular есть еще одна директива под названием ngClick, с помощью которой установить поведение элемента при клике на него. Вот мы постепенно и узнаем про мощь Angular, мы можем обойти все обработчики событий и использовать директиву ngClick. За основу возьмем наш пример выше, изменим его так, чтобы можно было менять username:
1 2 3 4 5 6 7 |
/** * changeUsername * Description: Updates the scope username */ $scope.changeUsername = function(username) { $scope.username = username; }; |
Теперь в нашем шаблоне можно напрямую воспользоваться директивой ngClick и подать ей на вход нужное значение. Ниже код HTML:
1 2 3 4 |
<p>Hello, <em>{{ username }}</em>!</p> <button ng-click="changeUsername('Bob')">Hello Bob?</button> <button ng-click="changeUsername('Adam')">Hello Adam?</button> <button ng-click="changeUsername('Elena')">Hello Elena?</button> |
При клике на кнопку, будет обновляться имя! Опять мы видим двустороннюю привязку данных. Все, что мы сделали, это обновили значение свойства в контроллере, а соответствующее значение уже отображается в DOM. Заметка: Все директивы Angular используют горбатый регистр (т.е. ngClick), а при использовании непосредственно в HTML меняется на ng-click.
Проходим в цикле по массиву с помощью ng-repeat
Часто в JS мы работаем с какими-то наборами данных, которые необходимо пройти в цикле. Для массивов вы использовали цикл for, пробегая массив и сохраняя необходимые результаты в строки для последующего вывода их в DOM. Для облегчения пробежки по массивам в Angular есть директива ngRepeat. Первым делом, создадим массив в контроллере:
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * usersArray * Description: A generic list of users, possibly pulled from a database, in * array notation. */ $scope.usersArray = [ ['BB', 'King'], ['Ray', 'Charles'], ['Muddy', 'Waters'], ['Lightnin', 'Hopkins'], ['Howlin', 'Wolf'] ]; |
В шаблоне HTML можно просто подключить директиву ngRepeat к тому элементу, содержимое которого необходимо пройти в цикле:
1 2 3 4 5 6 7 8 9 10 |
<table> <tr> <th>First Name</th> <th>Last Name</th> </tr> <tr ng-repeat="user in usersArray"> <td>{{ user[0] }}</td> <td>{{ user[1] }}</td> </tr> </table> |
Мы подключили директиву ngRepeat к тегу tr со строкой user in usersArray. Это значит, что тег tr будет зациклен, а переменная user будет заменяться значением на текущей итерации. Наш массив это просто набор подмассивов, и на первой итерации user[0] отобразит «BB», user[1] отобразит «King» (т.е. на нулевом шаге).
Проходим в цикле по массиву объектов с помощью ng-repeat
Часто в JS требуется работать с коллекцией объектов. Обычно, данные в таком формате возвращаются из баз данных или из API. Создадим типичную коллекцию объектов:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
$scope.usersObject = [ { firstname: 'BB', lastname: 'King' }, { firstname: 'Ray', lastname: 'Charles' }, { firstname: 'Muddy', lastname: 'Waters' }, { firstname: 'Lightnin', lastname: 'Hopkins' }, { firstname: 'Howlin', lastname: 'Wolf' } ]; |
По такой же логике можно пробежаться в цикле по коллекции объектов:
1 2 3 4 5 6 7 8 9 10 |
<table> <tr> <th>First Name</th> <th>Last Name</th> </tr> <tr ng-repeat="user in usersObject"> <td>{{ user.firstname }}</td> <td>{{ user.lastname }}</td> </tr> </table> |
Обратите внимание, как мы обращаемся к свойствам объекта с помощью точки! Просто и эффективно, двигаемся дальше.
Простой способ связи с введенными данными
Часто в приложениях нам приходится работать с данными из форм. В Angular есть крайне удобный способ связать введенные данные со значением свойств, сделать это можно с помощью директивы ngModel. Создадим в нашей модели случайную строку, и создадим функцию, которая будет отображать эту строку через alert:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * randomUserModel * Description: Initializes the random user model username */ $scope.randomUserModel = 'random user'; /** * randomUserModelAlert * Description: Alerts the random username available from the ng model. */ $scope.randomUserModelAlert = function() { alert($scope.randomUserModel); }; |
В HTML шаблоне можно связать данные из формы с моделью, тем самым открывая соединение привязки данных:
1 2 |
<input type="text" ng-model="randomUserModel"> <button ng-click="randomUserModelAlert()">alert my random name!</button> |
При любом изменении значения поля input, значение переменной автоматически также обновится. При вызове alert в функции (при помощи ngClick) отобразится уже обновленное значение.
Отображение и скрытие элементов DOM с помощью ng-show и ng-hide
ngShow и ngHide – две довольно аккуратные директивы в том смысле, что они напрямую манипулируют элементами DOM. DOM элементы показываются и скрываются на основе сравнения на true/false. Другими словами, если установить для тега ng-show=»true», то он будет отображаться. Соответственно, если установить ng-hide=»true», элемент будет скрыт. Чтобы показать работу директив нам даже не потребуется JavaScript. Создадим элемент checkbox , и посмотрим, каким образом Angular обрабатывает значения true/false. Ниже HTML код:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<input type="checkbox" id="box1" name="box1" ng-model="checkboxModel.box1"> <label for="box1">Show box1!</label> <br> <input type="checkbox" id="box2" name="box2" ng-model="checkboxModel.box2"> <label for="box2">Hide box2!</label> <div class="c-component__box" ng-show="checkboxModel.box1"> <h3>I am box 1</h3> <p>woo woo!</p> </div> <div class="c-component__box" ng-hide="checkboxModel.box2"> <h3>I am box 2</h3> <p>woo woo!</p> </div> |
Когда «Show box 1» выбран, свойство checkboxModel.box1 устанавливается в true. Т.е. при Angular подставляет ng-show=»checkboxModel.box1″. Таким же образом при выборе второго чекбокса, checkboxModel.box2 устанавливается в true, и блок 2 скрывается.
Изменение имени класса с помощью ng-class
Наше введение в Angular мы закончим на одной из моих любимых директив, ngClass, она позволяет динамически присваивать классы тегам HTML. Можете почитать о различных способах использования ngClass, а в нашем примере обойдемся очень простым кодом. Зададим пустое имя класса и создадим функцию, которая сможет менять это значение.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/** * textClass * Description: A generic class name to attach to a string of text */ $scope.textClass = ''; /** * changeTextClass * Description: Changes the text class */ $scope.changeTextClass = function(name) { $scope.textClass = name; } |
Присвоим значение textClass к атрибуту ng-class. А также привяжем к кнопке функцию changeTextClass:
1 2 |
<p class="c-component__text" ng-class="textClass">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Facere molestias explicabo aspernatur inventore nam fugit, nihil numquam distinctio totam hic, iure porro, magnam consequuntur nemo deleniti dicta amet quo assumenda.</p> <button ng-click="changeTextClass('pink')">Add a pink class</button> |
При клике на кнопку, будет вызываться функцию, которая обновляет значение свойства, а соответственно и имя класса. И вот так вот просто наш текст стал розовым, магия!
Заключение
Подведем итоги! В этом уроке «Введение в AngularJS. Примеры» мы рассмотрели примеры AngularJS, прошли только основы, но они уже могут вас заинтересовать для дальнейшего изучения Angular. Angular это просто зверь, и к нему стоит подходить аккуратно. В будущем, надеюсь, найду время на новые статьи по Angular. Так что следите за новостями!
Источник: //callmenick.com/
Редакция: Команда webformyself.