Улучшить эту документацию Посмотреть исходный код $compile
- $compileProvider
- сервис в модуле ng
Компилирует строку HTML или DOM в шаблон и генерирует функцию шаблона, которую можно использовать для связывания scope и шаблона.
Компиляция — это процесс обхода дерева DOM и сопоставления элементов DOM с директивами.
Полнофункциональный API директивы
Существует множество различных вариантов директивы.
Разница заключается в возвращаемом значении функции фабрики. Вы можете вернуть «объект определения директивы» (см. ниже), определяющий свойства директивы, или просто функцию postLink (все остальные свойства будут иметь значения по умолчанию).
Вот пример директивы, объявленной с помощью объекта определения директивы:
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>', // or // function(tElement, tAttrs) { ... },
// or
// templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
transclude: false,
restrict: 'A',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringAlias',
require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
// or
// return function postLink( ... ) { ... }
},
// or
// link: {
// pre: function preLink(scope, iElement, iAttrs, controller) { ... },
// post: function postLink(scope, iElement, iAttrs, controller) { ... }
// }
// or
// link: function postLink( ... ) { ... }
};
return directiveDefinitionObject;
});
Поэтому вышеприведенное можно упростить следующим образом:
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
// or
// return function postLink(scope, iElement, iAttrs) { ... }
});
Объект определения директивы
Объект определения директивы предоставляет инструкции компилятору компилятору. Атрибуты:
priority
Когда на одном элементе DOM определено несколько директив, иногда необходимо указать порядок их применения. priority используется для сортировки директив перед вызовом их compile функций. Приоритет определяется числом. Директивы с большим числовым priority компилируются первыми. Функции предварительной и последующей привязки также выполняются в порядке приоритета, но функции последующей привязки выполняются в обратном порядке. Порядок директив с одинаковым приоритетом не определен. По умолчанию приоритет 0.
terminal
Если установлено в значение true, то текущая priority будет последним набором директив, которые будут выполнены (любые директивы с текущим приоритетом также будут выполнены, так как порядок выполнения при одинаковом priority не определен).
scope
Если установлено в значение true, то для этой директивы будет создан новый контекст. Если несколько директив на одном элементе запрашивают новый контекст, создается только один новый контекст. Правило нового контекста не применяется для корня шаблона, так как корень шаблона всегда получает новый контекст.
Если установлено в значение {} (хеш объекта), то создается новый «изолированный» контекст. Изолированный контекст отличается от обычного контекста тем, что он не наследоваться от родительского контекста. Это полезно при создании переиспользуемых компонентов, которые не должны случайно считывать или изменять данные в родительском контексте.
Изолированный контекст принимает хеш объекта, который определяет набор локальных свойств контекста, полученных из родительского контекста. Эти локальные свойства полезны для алиасинга значений для шаблонов. Определение локалей — это хеш локального свойства контекста и его источника:
-
@или@attr— привязывает локальное свойство контекста к значению атрибута DOM. Результат всегда является строкой, так как атрибуты DOM являются строками. Если имя атрибута не указано, предполагается, что имя атрибута совпадает с локальным именем. Учитывая<widget my-attr="hello {{name}}">и определение виджетаscope: { localName:'@myAttr' }, то свойство контекста виджетаlocalNameбудет отражать интерполированное значениеhello {{name}}. При изменении атрибутаnameизменяется и свойствоlocalNameв контексте виджета.nameсчитывается из родительского контекста (а не контекста компонента). -
=или=attr— устанавливает двунаправленную привязку между локальным свойством контекста и свойством родительского контекста с именем, определенным через значение атрибутаattr. Если имя атрибута не указано, предполагается, что имя атрибута совпадает с локальным именем. Учитывая<widget my-attr="parentModel">и определение виджетаscope: { localModel:'=myAttr' }, то свойство контекста виджетаlocalModelбудет отражать значениеparentModelв родительском контексте. Любые изменения вparentModelбудут отражаться вlocalModel, и любые изменения вlocalModelбудут отражаться вparentModel. Если свойство родительского контекста не существует, будет выброшено исключение NON_ASSIGNABLE_MODEL_EXPRESSION. Вы можете избежать этого поведения, используя=?или=?attr, чтобы пометить свойство как необязательное. -
&или&attr— предоставляет способ выполнения выражения в контексте родительского контекста. Если имя атрибута не указано, предполагается, что имя атрибута совпадает с локальным именем. Учитывая<widget my-attr="count = count + value">и определение виджетаscope: { localFn:'&myAttr' }, свойство изолированного контекстаlocalFnбудет указывать на функцию-обёртку для выраженияcount = count + value. Часто желательно передавать данные из изолированного контекста в родительский контекст через выражение, это можно сделать, передав карту имен локальных переменных и их значений в функцию-обёртку fn. Например, если выражениеincrement(amount), то мы можем указать значение amount, вызвавlocalFnкакlocalFn({amount: 22}).
controller
Конструктор контроллера. Контроллер инициализируется до фазы предварительной привязки и используется другими директивами (см. атрибут require). Это позволяет директивам общаться друг с другом и расширять поведение друг друга. Контроллер инжектируется (и поддерживает обозначение скобок) с помощью следующих локальных переменных:
-
$scope— Текущий контекст, связанный с элементом -
$element— Текущий элемент -
$attrs— Текущий объект атрибутов для элемента -
$transclude— Функция связывания транклюзии, предварительно привязанная к правильному контексту транклюзии. Контекст можно переопределить, передав необязательный первый аргумент.function([scope], cloneLinkingFn).
require
Требует другую директиву и вводит её контроллер в качестве четвёртого аргумента функции связывания. require принимает строковое имя (или массив строк) директивы(ей), которую необходимо передать. Если используется массив, введённым аргументом будет массив в соответствующем порядке. Если такая директива не найдена или директива не имеет контроллера, возникает ошибка. Имя может быть префиксным:
- (без префикса) — Найти требуемый контроллер в текущем элементе. Выбросить ошибку, если не найдено.
-
?— Попытаться найти требуемый контроллер или передатьnullв функциюlinkв случае неудачи. -
^— Найти требуемый контроллер, выполнив поиск в элементе и его родительских элементах. Выбросить ошибку, если не найдено. -
?^— Попытаться найти требуемый контроллер, выполнив поиск в элементе и его родительских элементах, или передатьnullв функциюlinkв случае неудачи.
controllerAs
Псевдоним контроллера в области видимости директивы. Псевдоним для контроллера, чтобы к нему можно было обратиться в шаблоне директивы. Директива должна определять область видимости, чтобы эта настройка была использована. Полезно в случае, когда директива используется как компонент.
restrict
Строка подмножества EACM которые ограничивает директиву конкретным стилем объявления директивы. Если пропущено, используется значение по умолчанию (только атрибуты).
-
E— Имя элемента:<my-directive></my-directive> -
A— Атрибут (по умолчанию):<div my-directive="exp"></div> -
C— Класс:<div class="my-directive: exp;"></div> -
M— Комментарий:<!-- directive: my-directive exp -->
template
HTML-разметка, которая может:
- Заменить содержимое элемента директивы (по умолчанию).
- Заменить сам элемент директивы (если
replaceравно true — УСТАРЕЛО). - Оборачивает содержимое элемента директивы (если
transcludeравно true).
Значение может быть:
- Строкой. Например
<div red-on-hover>{{delete_str}}</div>. - Функцией, которая принимает два аргумента
tElementиtAttrs(описаны в API функцииcompile) и возвращает строковое значение.
templateUrl
То же самое, что и template, но шаблон загружается по указанному URL-адресу. Поскольку загрузка шаблона асинхронна, компиляция/связывание приостанавливается до тех пор, пока шаблон не загрузится.
Вы можете указать templateUrl как строку, представляющую URL-адрес, или как функцию, которая принимает два аргумента tElement и tAttrs (описаны в API функции compile) и возвращает строковое значение, представляющее URL-адрес. В любом случае URL-адрес шаблона передается через $sce.getTrustedResourceUrl.
replace ([УСТАРЕЛО!], будет удалено в следующей версии)
указать, что должен заменить шаблон. По умолчанию false.
-
true— шаблон заменит элемент директивы. -
false— шаблон заменит содержимое элемента директивы.
Процесс замены мигрирует все атрибуты/классы со старого элемента на новый. См. Руководство по директивам для примера.
transclude
скомпилировать содержимое элемента и сделать его доступным для директивы. Обычно используется с ngTransclude. Преимущество транклюзии заключается в том, что функция связывания получает функцию транклюзии, которая предварительно привязана к правильному контексту. В типичной настройке виджет создаёт isolate контекст, но транклюзия не является дочерним элементом, а является братом isolate контекста. Это позволяет виджету иметь собственное состояние, а транклюзия привязана к родительскому (предварительно isolate) контексту.
Существует два типа транклюзии в зависимости от того, хотите ли вы транклюдировать только содержимое элемента директивы или весь элемент:
-
true- транслировать содержимое (т.е. дочерние узлы) элемента директивы. -
'element'- транслировать весь элемент директивы, включая все директивы в этом элементе, определённые с более низким приоритетом, чем эта директива. При использовании свойствоtemplateигнорируется.
compile
function compile(tElement, tAttrs, transclude) { ... }
Функция compile отвечает за преобразование шаблона DOM. Поскольку большинство директив не выполняют преобразование шаблона, она используется не часто. Функция compile принимает следующие аргументы:
-
tElement- элемент шаблона - Элемент, в котором объявлена директива. Безопасно выполнять преобразование шаблона только на элементе и его дочерних элементах. -
tAttrs- атрибуты шаблона - Нормализованный список атрибутов, объявленных в этом элементе, общий для всех функций компиляции директив. -
transclude- [УСТАРЕЛО!] Функция связывания трансклюзии:function(scope, cloneLinkingFn)
template или templateUrl объявления или ручной компиляции внутри функции compile. transclude , передаваемая функции compile, устарела, так как, например, она не знает правильного внешнего контекста. Пожалуйста, используйте функцию transclude, передаваемую функции link, вместо неё. Функция compile может возвращать значение, которое может быть либо функцией, либо объектом.
-
возвращение функции (после связывания) - эквивалентно регистрации функции связывания через свойство
linkобъекта конфигурации, когда функция compile пустая. -
возвращение объекта с функциями, зарегистрированными через
preиpostсвойства - позволяет управлять временем вызова функции связывания во время фазы связывания. См. информацию о функциях до-связывания и после-связывания ниже.
link
Это свойство используется только в том случае, если свойство compile не определено.
function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
Функция link отвечает за регистрацию обработчиков событий DOM и обновление DOM. Она выполняется после клонирования шаблона. Именно здесь будет размещена большая часть логики директивы.
-
scope- Область видимости - Область видимости, используемая директивой для регистрации наблюдений. -
iElement- элемент экземпляра - Элемент, где используется директива. Безопасно манипулировать только дочерними элементами в функцииpostLink, так как дочерние элементы уже были связаны. -
iAttrs- атрибуты экземпляра - Нормализованный список атрибутов, объявленных в этом элементе, общий для всех функций связывания директив. -
controller- экземпляр контроллера - Экземпляр контроллера, если хотя бы одна директива в элементе определяет контроллер. Контроллер используется всеми директивами, что позволяет директивам использовать контроллеры в качестве канала связи. -
transcludeFn- функция связывания трансклюзии, предварительно связанная с правильной областью видимости трансклюзии. Область видимости может быть переопределена необязательным первым аргументом. Это то же самое, что и параметр$transcludeконтроллеров директив.function([scope], cloneLinkingFn).
Функция до-связывания
Выполняется до связывания дочерних элементов. Небезопасно выполнять преобразование DOM, так как функция компилятора связывания не сможет найти правильные элементы для связывания.
Функция после-связывания
Выполняется после связывания дочерних элементов. Безопасно выполнять преобразование DOM в функции после-связывания.
Атрибуты
Объект Атрибуты - передается в качестве параметра в функции link() или compile(). Он имеет множество применений.
доступ к нормализованным именам атрибутов: Директивы, такие как 'ngBind', могут быть выражены различными способами: 'ng:bind', data-ng-bind, или 'x-ng-bind'. Объект атрибутов позволяет получить доступ к атрибутам в нормализованном виде.
-
Взаимодействие директив: Все директивы используют один и тот же экземпляр объекта атрибутов, что позволяет директивам использовать объект атрибутов для меж-директивного взаимодействия.
-
Поддержка интерполяции: Атрибуты интерполяции назначаются объекту атрибутов, позволяя другим директивам читать интерполированное значение.
-
Наблюдение за интерполированными атрибутами: Используйте
$observeдля наблюдения за изменениями значений атрибутов, содержащих интерполяцию (например,src="{{bar}}"). Это не только очень эффективно, но и единственный простой способ получить фактическое значение, потому что во время фазы связывания интерполяция ещё не была вычислена, и поэтому значение в это время установлено вundefined.
function linkingFn(scope, elm, attrs, ctrl) {
// get the attribute value
console.log(attrs.ngModel);
// change the attribute
attrs.$set('ngModel', 'new value');
// observe changes to interpolated attribute
attrs.$observe('ngModel', function(value) {
console.log('ngModel has changed value to ' + value);
});
}
module.directive. Приведенный ниже пример иллюстрирует работу $compile . Использование
$compile(element, transclude, maxPriority);
Аргументы
| Параметр | Тип | Подробности |
|---|---|---|
| элемент | stringDOMElement | Элемент или строка HTML для компиляции в функцию шаблона. |
| transclude | function(angular.Scope, cloneAttachFn=) | функция, доступная для директив. |
| maxPriority | number | применить только директивы с более низким приоритетом (влияет только на корневой элемент(ы), а не на их дочерние элементы) |
Возвращаемое значение
function(scope, cloneAttachFn=) |
функция связывания, используемая для привязки шаблона (элемент/дерево DOM) к области видимости. Где:
Вызов функции связывания возвращает элемент шаблона. Это либо исходный элемент, переданный в функцию, либо клон элемента, если После связывания представление не обновляется до вызова $digest, который обычно выполняется Angular автоматически. Если вам нужен доступ к связанному представлению, есть два способа:
Дополнительную информацию о работе компилятора см. в разделе Angular HTML Компилятор Руководства разработчика. |
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.2.32/docs/api/ng/service/$compile