Улучшить эту документациюОбзор концепций
В этом разделе кратко рассматриваются все важные части AngularJS с помощью простого примера. Для более подробного объяснения см. учебник.
| Концепция | Описание |
|---|---|
| Шаблон | HTML с дополнительными метками |
| Директивы | расширяют HTML с помощью пользовательских атрибутов и элементов |
| Модель | данные, отображаемые пользователю в представлении и с которыми взаимодействует пользователь |
| Область видимости | контекст, в котором хранится модель, чтобы контроллеры, директивы и выражения могли к ней обратиться |
| Выражения | доступ к переменным и функциям из области видимости |
| Компилятор | анализирует шаблон и инициализирует директивы и выражения |
| Фильтр | форматирует значение выражения для отображения пользователю |
| Представление | то, что видит пользователь (DOM) |
| Привязка данных | синхронизирует данные между моделью и представлением |
| Контроллер | бизнес-логика за представлениями |
| Внедрение зависимостей | Создаёт и подключает объекты и функции |
| Инжектор | контейнер для внедрения зависимостей |
| Модуль | контейнер для разных частей приложения, включая контроллеры, сервисы, фильтры, директивы, которые настраивают Инжектор |
| Сервис | многократно используемая бизнес-логика, независимая от представлений |
Первый пример: Привязка данных
В следующем примере мы создадим форму для расчёта стоимости счета в разных валютах.
Давайте начнём с полей ввода для количества и стоимости, значения которых умножаются для получения общей суммы счета:
Попробуйте Live Preview выше, а затем давайте пройдёмся по примеру и опишем, что происходит.
Это выглядит как обычный HTML с некоторыми новыми разметками. В Angular файл такого рода называется "шаблоном. Когда Angular запускает ваше приложение, он анализирует и обрабатывает эту новую разметку из шаблона с помощью так называемого "компилятора. Загруженный, преобразованный и рендеренный DOM затем называется "представлением".
Первый тип новой разметки - так называемые "директивы. Они применяют специальное поведение к атрибутам или элементам в HTML. В примере выше мы используем атрибут ng-app, который связан с директивой, автоматически инициализирующей наше приложение. Angular также определяет директиву для элемента input, которая добавляет дополнительное поведение к элементу. Директива ng-model хранит/обновляет значение поля ввода в/из переменной.
Второй тип новой разметки - фигурные скобки {{ expression | filter }}: Когда компилятор встречает эту разметку, он заменит её вычисленным значением разметки. "Выражение" в шаблоне - это фрагмент кода, похожий на JavaScript, который позволяет читать и записывать переменные. Обратите внимание, что эти переменные не являются глобальными переменными. Так же, как переменные в функции JavaScript существуют в области видимости, Angular предоставляет "область видимости для переменных, доступных для выражений. Значения, которые хранятся в переменных в области видимости, в остальной документации называются "моделью".
Применительно к вышеприведённому примеру разметка указывает Angular "взять данные, полученные из полей ввода, и перемножить их".
В приведённом примере также есть "фильтр. Фильтр форматирует значение выражения для отображения пользователю. В примере выше фильтр currency форматирует число в вид, похожий на денежную сумму.
Важный момент в примере заключается в том, что Angular обеспечивает живую привязку: всякий раз, когда меняются значения ввода, значение выражений автоматически пересчитывается, а DOM обновляется с их значениями. Концепция, лежащая в основе этого, - "двусторонняя привязка данных.
Добавление UI-логики: Контроллеры
Давайте добавим немного больше логики в пример, который позволит вводить и рассчитывать стоимость в разных валютах, а также оплачивать счет.
Что изменилось?
Во-первых, есть новый JavaScript-файл, который содержит так называемый "контроллер. Точнее, файл содержит функцию-конструктор, которая создаёт фактический экземпляр контроллера. Цель контроллеров - предоставлять переменные и функциональность выражениям и директивам.
Помимо нового файла, содержащего код контроллера, мы также добавили директиву ng-controller в HTML. Эта директива сообщает Angular, что новый InvoiceController отвечает за элемент с директивой и все дочерние элементы. Синтаксис InvoiceController as invoice сообщает Angular об инициализации контроллера и сохранении его в переменной invoice в текущей области видимости.
Мы также изменили все выражения на странице, чтобы они считывали и записывали переменные внутри экземпляра контроллера, добавив invoice. . Возможные валюты определяются в контроллере и добавляются в шаблон с помощью ng-repeat. Поскольку контроллер содержит функцию total, мы также можем привязать результат этой функции к DOM с помощью {{ invoice.total(...) }}.
Опять же, эта привязка является живой, то есть DOM будет автоматически обновляться всякий раз, когда результат функции меняется. Кнопка для оплаты счета использует директиву ngClick. Это вызовет соответствующее выражение всякий раз, когда нажимается кнопка.
В новом JavaScript-файле мы также создаём модуль, в котором регистрируем контроллер. Мы поговорим о модулях в следующем разделе.
Следующая диаграмма показывает, как всё работает вместе после введения контроллера:
Бизнес-логика, независимая от представления: Сервисы
Сейчас InvoiceController содержит всю логику нашего примера. Когда приложение растёт, хорошей практикой является перемещение бизнес-логики, независимой от представления, из контроллера в сервис, чтобы её можно было повторно использовать в других частях приложения. Позже мы также можем изменить этот сервис на загрузку курсов валют из веб-источника, например, вызвав API Yahoo Finance, без изменения контроллера.
Давайте переработаем наш пример и перенесём конвертацию валюты в сервис в другой файл:
Что изменилось? Мы переместили функцию convertCurrency и определение существующих валют в новый файл finance2.js. Но как контроллер получает доступ к теперь отделённой функции?
Здесь на помощь приходит "внедрение зависимостей. Внедрение зависимостей (DI) - это паттерн проектирования программного обеспечения, который описывает, как создаются объекты и функции, и как они получают доступ к своим зависимостям. Всё в Angular (директивы, фильтры, контроллеры, сервисы и т. д.) создаётся и подключается с помощью внедрения зависимостей. В Angular контейнер DI называется "инжектором.
Для использования DI необходимо место, где регистрируются все объекты, которые должны работать вместе. В Angular это предназначение так называемых "модулей. Когда Angular запускается, он использует конфигурацию модуля с именем, определённым директивой ng-app , включая конфигурацию всех модулей, от которых этот модуль зависит.
В примере выше: шаблон содержит директиву ng-app="invoice2". Это сообщает Angular использовать модуль invoice2 в качестве основного модуля приложения. Фрагмент кода angular.module('invoice2', ['finance2']) указывает, что модуль invoice2 зависит от модуля finance2. Таким образом, Angular использует InvoiceController и сервис currencyConverter.
Теперь, когда Angular знает обо всех частях приложения, ему нужно их создать. В предыдущем разделе мы видели, что контроллеры создаются с помощью фабричной функции. Для сервисов есть несколько способов определить их фабрику (см. руководство по сервисам). В примере выше мы используем функцию, которая возвращает функцию currencyConverter в качестве фабрики для сервиса.
Вернёмся к исходному вопросу: как InvoiceController получает ссылку на функцию currencyConverter? В Angular это делается путём простого определения аргументов в функции-конструкторе. Таким образом, инжектор может создавать объекты в нужном порядке и передавать ранее созданные объекты в фабрики объектов, которые зависят от них. В нашем примере InvoiceController имеет аргумент по имени currencyConverter. Таким образом, Angular знает о зависимости между контроллером и сервисом и вызывает контроллер с экземпляром сервиса в качестве аргумента.
Последнее изменение в примере между предыдущим разделом и этим разделом заключается в том, что теперь мы передаём массив функции module.controller вместо простой функции. Массив сначала содержит имена зависимостей сервиса, которые нужны контроллеру. Последний элемент массива - это конструктор функции контроллера. Angular использует этот синтаксис массива для определения зависимостей, чтобы DI также работало после минификации кода, что, скорее всего, переименует имя аргумента конструктора контроллера в что-то более короткое, например, a.
Доступ к бэкенду
Завершим наш пример, получив курсы валют из API Yahoo Finance. Следующий пример демонстрирует, как это делается с Angular:
Что изменилось? Наш currencyConverter сервис модуля finance теперь использует $http, встроенный в Angular сервис для доступа к серверному бэкенду. $http — это обёртка вокруг XMLHttpRequest и транспортов JSONP.
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.3.20/docs/guide/concepts