Использование директив в AngularJS: Теория и практика

| Пятница, 30 августа, 2013

Метки: AngularJS, Javascript Комментарии: 0

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

Применение директив в HTML

К именам директив применяется верблюжий регистр (CamelCase, то есть все слова пишутся слитно без пробелов, но каждое слово начинается с заглавной буквы). Но также директивы могут быть вызваны путем преобразования верблюжьего регистра в змеиный, то есть применяя специальные символы: '-' или '_'. Необязательно имена директив могут предваряться символами 'x-' или 'data-' чтобы сделать эти директивы компилируемыми. Приведем примеры некоторых имен, подходящих для директив: ng:bind, ng-bind, ng_bind и data-ng-bind.

Директивы могут быть прописаны в виде имен элементов, атрибутов, имен классов, а также и в комментариях. Ниже покажем некоторые равнозначащие примеры использования директивы myDir. (Хотя иногда некоторые директивы ограничены только использованием в виде атрибутов)

<span my-dir="exp"></span>
<span class="my-dir: exp;"></span>
<my-dir></my-dir>
<!-- directive: my-dir exp -->

Директивы могут быть заданы различными способами, но результат их работа должен быть одинаков, как в примере ниже:

<!doctype html>
<html ng-app>
  <head>
    <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js"></script>
    <script src="script.js"></script>
  </head>
  <body>
    <div ng-controller="Ctrl1">
      Hello <input ng-model='name'> <hr/>
      &lt;span ng:bind="name"&gt; <span ng:bind="name"></span> <br/>
      &lt;span ng_bind="name"&gt; <span ng_bind="name"></span> <br/>
      &lt;span ng-bind="name"&gt; <span ng-bind="name"></span> <br/>
      &lt;span data-ng-bind="name"&gt; <span data-ng-bind="name"></span> <br/>
      &lt;span x-ng-bind="name"&gt; <span x-ng-bind="name"></span> <br/>
    </div>
  </body>
</html>
function Ctrl1($scope) {
  $scope.name = 'angular';
}
it('should show off bindings', function() {
  expect(element('div[ng-controller="Ctrl1"] span[ng-bind]').text()).toBe('angular');
});
Живой пример
Hello
<span ng:bind="name">
<span ng_bind="name">
<span ng-bind="name">
<span data-ng-bind="name">
<span x-ng-bind="name">

Связывание текста и атрибутов

Во время процесса компиляции compilator (внутренний сервис Angular) ищет текст и атрибуты с помощью другого сервиса $interpolate, который ведет поиск встроенных выражений (expressions). Эти выражения зарегистрированы в объектах $watch, и обновляются при каждой внутренней итерации цикла элемента digest.

Пример такой интерполяции (вставки) приведем здесь:

Hello {{username}}!

Связка c атрибутом, имеющим префикс ngAttr

Если атрибут для связывания имеет префикс ngAttr (в денормализованном виде 'ng-attr-', 'ng:attr-'), то во время компиляции этот префикс будет удален и связывание будет применено к атрибуту без префикса. Этот прием позволяет делать связку с атрибутами, которые жадно схватываются сначала самими браузерами в неоткомпилированной форме (например, img[src] или svg-атрибуты, типа circle[cx]).

Для примера рассмотрим такой шаблон:

<svg>
  <circle ng-attr-cx="{{cx}}"></circle>
</svg>

Модели cx присвоено значение 5, результатом после компиляции шаблона в DOM будет такой код:

<svg>
  <circle cx="5"></circle>
</svg>

Если бы связка {{cx}} была бы установлена прямо с атрибутом cx. То вышла бы ошибка: Error: Invalid value for attribute cx={{cx}}. С атрибутом ng-attr-cx таких проблем удается избежать.

Процесс компиляции и поиск директив

Компиляция HTML происходит в три этапа:

  1. Сначала HTML разбирается, анализируется и преобразовывается в DOM стандартными механизмами браузеров (API). Это важно понимать, потому что шаблон должен представлять собой правильно структурированный HTML, который будет хорошо парситься браузерами. Это в противоположность большинству систем работы с шаблонами, которые работают со строками, а не с DOM-элементами.
  2. Далее компиляция DOM выполняется в Angular путем вызова метода $compile(). Этот метод пробегает по всем элементам DOM и ищет директивы. Если найдена директива, она добавляется в список директив, который ассоциирован с текущим обрабатываемым элементом DOM. Как только все директивы для текущего DOM элемента идентифицированы, они сортируются по приоритету, и запускаются их функции compile(). Эти функции - compile(), потенциально могут изменить структуру DOM, и поэтому они ответственны за создание функций link(), которые будут объяснены далее. Метод $compile() в качестве возвращаемого объекта выдает объединяющую связующую функцию, которая является коллекцией всех связующих функций, возвращаемых из компилируемых функций каждой отдельной директивы.
  3. Связывание шаблона с областью видимости (scope) происходит при вызове связующей функции, описанной в предыдущем шаге. Это, в свою очередь, произведет вызов каждой связующей функции для каждой директивы, тем самым позволяя зарегистрировать прослушивание(listeners) элементов DOM, и установить объекты наблюдения (watches) за областью видимости (scope). Результатом всех этих действий будет живая связка между областью видимости (scope) и элементами DOM. Изменения в scope сразу передаются в DOM.
var $compile = ...; // injected into your code
var scope = ...;
 
var html = '<div ng-bind="exp"></div>';
 
// Step 1: parse HTML into DOM element
var template = angular.element(html);
 
// Step 2: compile the template
var linkFn = $compile(template);
 
// Step 3: link the compiled template with the scope.
linkFn(scope);

Комментарии
Никто еще не оставил здесь комментарий.
Войдите, чтобы написать комментарий , или воспользуйтесь формой ниже.
 

Copyright © CodeHint.ru 2013-2024 (v2.4.7 - работает на Angular Universal)Калькулятор инвест-портфеля