среда, 18 декабря 2013 г.

Введение в AngularJS

Наши возможности по созданию веб-приложений невероятны. Но также велики и сложности при создании веб-приложений. Команда Angular ставит своей целью облегчить трудности связанные с разработкой AJAX приложений. Google имея богатый опыт создания крупных веб-приложений, таких как Gmail, Maps, Календарь и многих других решила использовать этот опыт на благо всех.
Любой разработчик хотел бы создавать веб-приложения и получать от этого удовольствие. Мы все хотим, чтобы процесс кодирования был более похож на творчество и менее похож на попытки удовлетворить странные внутренние потребности веб-браузера.
В то же время, мы хотим среду, которая с самого начала помогает нам делать дизайн приложения понятным и легким, а также делать наше приложение таким, чтобы его можно было легко тестировать, расширять и поддерживать, когда оно становятся большим.
Google попытался реализовать такую среду в Angular.

Основные понятия

Есть несколько основных идей, которые вы будете использовать во всех Angular приложениях. Как оказалось, среди них нет ничего нового. Вместо этого, были заимствованы успешные идеи из других сред разработки и реализованы путем, который охватывает HTML, JavaScript и многие другие знакомые веб-стандарты.

Client-Side Templates

Multi-page веб-приложения создают свой HTML путем сборки шаблона и данных на стороне сервера, и загрузкой готовой страницы в браузер. Single-page приложения - также известные как AJAX приложения - делают это в некоторой степени также. Angular отличается тем, что шаблон и данные отправляются в браузер, чтобы быть собраны там. Роль сервера, состоит только в сохранении статических ресурсов шаблонов и хранения данных, необходимых для этих шаблонов.

Давайте посмотрим пример того, как происходит соединение данных и шаблона в Angular. Мы возьмем пример Hello, World, но вместо написания "Hello, World" в виде одной строки, сохраним приветствие "Hello" в структуре greeting, чтобы иметь возможность изменить его позже.

Для этого мы создадим наш шаблон в hello.html:
<html ng-app>
 <head>
  <script src="angular.js"></script>
  <script src="controllers.js"></script>
 </head>
 <body>
  <div ng-controller='HelloController'>
   <p>{{greeting.text}}, World</p>
  </div>
 </body>
</html>
Логику разместим в controllers.js:
function HelloController($scope) {
 $scope.greeting = { text: 'Hello' };
}
После загрузки hello.html браузер отобразит “Hello, World”.


Здесь есть несколько интересных моментов в сравнении с практикой, широко используемой на сегодняшний день:
  • В шаблоне нет классов или IDs для определения того к какому элементу прикрепляются обработчики событий.
  • Для того чтобы на странице отобразилось значение Hello, которое храниться в greeting.text контроллера HelloController, мы не регистрировали ни обработчиков событий ни функций обратного вызова.
  • HelloController это обычный класс JavaScript, и никак не связан с Angular.
  • HelloController получил объект $scope не создавая его.
  • Мы не должны вызывать конструктор для HelloController или определять когда он вызывается.
Далее мы рассмотрим больше отличий, но уже сейчас ясно что структура Angular-приложения отлична от аналогичных традиционных приложений.
Для того чтобы понять почему был выбран такой дизайн и как работает Angular следует рассмотреть некоторые идеи, которые Angular позаимствовал из других источников.

Model View Controller (MVC)

Паттерн MVC был введен в 1970 году в рамках Smalltalk. С момента своего появления в Smalltalk, MVC стал популярным почти во всех средах разработки где были задействованы пользовательские интерфейсы.
Основной идеей MVC является то, что в коде есть четкое разделение между данными(модель), логикой(контроллер) и представлением данных для пользователя(вид).
Вид получает данные из модели и отображает их пользователю. Когда пользователь взаимодействует с приложением, контроллер реагирует на это, изменяя данные в модели. Наконец, модель уведомляет представление о том, что произошло изменение, чтобы оно могло обновиться.
В Angular-приложении вид это Document Object Model (DOM), контроллер это классы JavaScript, а модель это данные хранящиеся в свойствах объекта. 
MVC является хорошим выбором. Кроме того, что этот паттерн широко известен и популярен, он дает большие преимущества при создании приложения - приложение легче расширять, поддерживать и тестировать.

Data Binding

До AJAX single-page-приложения были обычным делом, платформы, такие как Rails, PHP, или JSP помогали создавать пользовательский интерфейс (UI) путем слияния строк HTML с данными перед отправкой его клиенту. Библиотеки подобные jQuery распространили эту модель на клиента, но с возможностью обновления части DOM отдельно, а не обновлять всю страницу. Здесь мы объединяем строки HTML шаблона с данными, а затем вставляем результат в DOM устанавливая innerHtml  родительского элемента.

Это все работает довольно хорошо, но когда вы хотите вставить обновленные данные в UI, или изменить данные на основе пользовательского ввода, вам надо сделать немного нетривиальной работы, чтобы убедиться, что данные содержат правильные значения, как в UI так и в свойствах JavaScript.

Но, что если бы мы могли проделать эту работу без написания кода? Что, если просто объявить какая часть UI связана с JavaScript свойствами и получить их автоматическую синхронизацию. Такой стиль программирования называется data binding. Разработчики включили его в Angular потому, что он прекрасно работает с MVC для минимизации при создании вида и модели. Большая часть работы по передаче данных от одной части к другой происходит автоматически.

Чтобы увидеть это в действии, возьмем наш пример и сделаем его динамическим.
HelloController устанавливает модель greeting.text один раз и это значение больше не меняется. Чтобы иметь возможность менять это значение добавим элемент для ввода текста, который сможет изменить значение greeting.text когда пользователь вводит текст.

Вот новый шаблон:
<html ng-app>
 <head>
  <script src="angular.js"></script>
  <script src="controllers.js"></script>
 </head>
 <body>
  <div ng-controller='HelloController'>
   <input ng-model='greeting.text'>
   <p>{{greeting.text}}, World</p>
  </div>
 </body>
</html>

Контроллер HelloController остается как есть.
После загрузки hello.html окно браузера будет выглядеть как скриншоте:


Если в поле ввода вместо Hello напечатать Hi, то окно браузера будет выглядеть так:


Даже не регистрируя обработчика события на изменение поля ввода, мы получили UI который будет динамически обновляться. Тоже самое будет справедливо и для  изменений приходящих со стороны сервера. В нашем контроллере мы могли бы сделать запрос на наш сервер, получить ответ и установить $scope.greeting.text. Angular автоматически обновит и поле ввода и текст помещенный внутри фигурных скобок.

Dependency Injection

Многое из того с чем работает HelloController мы не должны создавать явно. Например объект $scope, который осуществляет связывание данных, передается нам автоматически. Мы не должны создавать его. Мы просто запрашиваем его через объявление в конструкторе HelloController.
$Scope не единственный объект, который мы можем запросить. Если мы хотим связать данные с URL в браузере, мы можем запросить объект, который этим управляет, поместив $location в конструкторе следующим образом.
function HelloController($scope, $location) {
$scope.greeting = { text: 'Hello' };
// use $location for something good here...
}
Такой эффект получается благодаря системе dependency injection. Dependency injection позволяет нам следовать стилю разработки в котором вместо того чтобы создавать зависимости наши классы просто запрашиваю то, что им нужно.

Такой стиль соответствует паттерну под названием "Закон Деметры", также известный как принцип малого знания. Поскольку работа контроллера HelloController состоит в создании начального состояния для модели greeting, этот паттерн утверждает, что не надо беспокоится ни о том как создается $scope ни о том где он находится.

Эта возможность существует не только для объектов, созданных Angular. Мы можем написать любой код и использовать его также.

Directives

Одним из лучших свойств Angular является то, что вы можете писать свои шаблоны как HTML. Это возможно потому, что в ядро Angular включен мощный движок преобразования DOM, который позволяет вам расширять HTML синтаксис.

В наших шаблонах мы уже видели несколько новых атрибутов, которые не являются частью HTML спецификации. Например двойные скобки {{}} для привязки данных, ng-controller для определения контроллера и ng-model которая связывает input c моделью. Эти расширения HTML называются директивами.

Angular поставляется с большим количеством директив, которые помогают вам определить вид ваших приложений. Директивы могут декларативно настроить то, как работает ваше приложение или быть использованы для создания многократно используемых компонентов.

Вы не ограничены директивами которые поставляются с Angular. Вы можете писать свои собственные расширения HTML, которые делают все необходимые действия.