Улучшить документацию Просмотреть исходный код $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',
templateNamespace: 'html',
scope: false,
controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
controllerAs: 'stringIdentifier',
bindToController: false,
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) { ... }
});
Объект определения директивы
Объект определения директивы предоставляет инструкции компилятору компилятора. Атрибуты:
multiElement
При установке этого свойства в значение true, компилятор HTML соберет узлы DOM между узлами с атрибутами directive-name-start и directive-name-end, и сгруппирует их вместе как элементы директивы. Рекомендуется использовать эту функцию для директивы, которая не является строго поведенческой (например, ngClick), и которая не изменяет или не заменяет дочерние узлы (например, ngInclude).
priority
Когда несколько директивы определены на одном элементе DOM, иногда необходимо указать порядок применения директивы. Свойство priority используется для сортировки директивы перед вызовом их функций compile. Приоритет определяется как число. Директивы с более высокими числовыми значениями priority компилируются первыми. Функции предварительной привязки также выполняются в порядке приоритета, но функции после привязки выполняются в обратном порядке. Порядок директивы с одинаковым приоритетом не определён. Значение приоритета по умолчанию — 0.
terminal
Если установлено в значение true, то текущая priority будет последней набором директивы, которые будут выполнены (любые директивы в текущем приоритете всё равно будут выполнены, так как порядок выполнения директивы с одинаковым priority не определён). Обратите внимание, что выражения и другие директивы, используемые в шаблоне директивы, также будут исключены из выполнения.
scope
Если установлено в значение true, то для этой директивы будет создан новый контекст. Если несколько директивы на одном элементе запрашивают новый контекст, создаётся только один новый контекст. Правило создания нового контекста не применяется к корню шаблона, так как корень шаблона всегда получает новый контекст.
Если установлено в значение {} (хеш объекта), то создаётся новый изолированный контекст. Изолированный контекст отличается от обычного контекста тем, что он не наследует свойства от родительского контекста. Это полезно при создании повторно используемых компонентов, которые не должны случайно читать или изменять данные в родительском контексте.
Изолированный контекст принимает хеш объекта, который определяет набор локальных свойств контекста, полученных из родительского контекста. Эти локальные свойства полезны для алиасов значений для шаблонов. Определение локалей — это хеш локального свойства контекста и его источника:
-
@или@attr— привязывает локальное свойство контекста к значению атрибута DOM. Результатом всегда является строка, так как атрибуты DOM являются строками. Если имя атрибутаattrне указано, предполагается, что имя атрибута совпадает с именем локальной переменной. Учитывая<widget my-attr="hello {{name}}">и определение виджетаscope: { localName:'@myAttr' }, свойство контекста виджетаlocalNameотражает интерполированное значениеhello {{name}}. По мере изменения атрибутаnameизменяется свойствоlocalNameв контексте виджета.nameсчитывается из родительского контекста (а не контекста компонента). -
=или=attr— устанавливает двунаправленную привязку между локальным свойством контекста и свойством родительского контекста с именем, определённым через значение атрибутаattr. Если имя атрибутаattrне указано, предполагается, что имя атрибута совпадает с именем локальной переменной. Учитывая<widget my-attr="parentModel">и определение виджетаscope: { localModel:'=myAttr' }, свойство контекста виджетаlocalModelотражает значениеparentModelв родительском контексте. Любые изменения вparentModelбудут отражаться вlocalModel, и любые изменения вlocalModelбудут отражаться вparentModel. Если свойство родительского контекста не существует, будет выброшено исключение NON_ASSIGNABLE_MODEL_EXPRESSION. Вы можете избежать этого поведения, используя=?или=?attrдля обозначения свойства как необязательного. Если вы хотите выполнять неглубокий отслеживание изменений (т.е. $watchCollection вместо $watch), вы можете использовать=*или=*attr(=*?или=*?attrесли свойство необязательно). -
&или&attr— обеспечивает возможность выполнения выражения в контексте родительского контекста. Если имя атрибутаattrне указано, предполагается, что имя атрибута совпадает с именем локальной переменной. Учитывая<widget my-attr="count = count + value">и определение виджетаscope: { localFn:'&myAttr' }, свойство изолированного контекстаlocalFnбудет указывать на оболочку функции для выраженияcount = count + value. Часто желательно передавать данные из изолированного контекста через выражение в родительский контекст. Это можно сделать, передав карту имён локальных переменных и их значений в функцию-оболочку выражения. Например, если выражениеincrement(amount), то мы можем указать значение amount, вызвавlocalFnкакlocalFn({amount: 22}).
bindToController
При использовании изолированного контекста для компонента (см. выше), и использовании controllerAs, bindToController: true позволит компоненту привязывать свои свойства к контроллеру, а не к контексту. При создании контроллера начальные значения привязок изолированного контекста уже доступны.
controller
Конструктор контроллера. Контроллер инициализируется до фазы предварительной привязки и совместно используется с другими директивами (см. атрибут require). Это позволяет директивам взаимодействовать друг с другом и расширять поведение друг друга. Контроллер является инъекционным (и поддерживает обозначение квадратными скобками) со следующими локальными переменными:
-
$scope— Текущий контекст, связанный с элементом -
$element— Текущий элемент -
$attrs— Текущий объект атрибутов для элемента -
$transclude— Функция привязки трансклюзии, предварительно связанная с правильным контекстом трансклюзии:function([scope], cloneLinkingFn, futureParentElement).-
scope: необязательный аргумент для переопределения контекста. -
cloneLinkingFn: необязательный аргумент для создания клонов исходного трансклюдированного содержимого. -
futureParentElement:- определяет родителя, к которому
cloneLinkingFnдобавит клонированные элементы. - значение по умолчанию:
$element.parent()соответственно$elementдляtransclude:'element'соответственноtransclude:true. - необходимо только для трансклюзий, которые могут содержать элементы, не являющиеся HTML (например, SVG-элементы), и когда передан
cloneLinkinFn, так как эти элементы должны создаваться и клонироваться особым способом, когда они определены вне своих обычных контейнеров (например, как<svg>). - См. также свойство
directive.templateNamespace.
- определяет родителя, к которому
-
require
Требует другую директиву и вводит её контроллер в качестве четвёртого аргумента функции привязки. require принимает строковое имя (или массив строк) директивы(ей) для передачи. Если используется массив, введённый аргумент будет массивом в соответствующем порядке. Если такая директива не найдена или у директивы нет контроллера, возникает ошибка (если не указана функция привязки, проверка ошибок пропускается). Имя может быть префиксным:
- (без префикса) — Поиск требуемого контроллера в текущем элементе. Выбрасывает ошибку, если не найден.
-
?— Попытка найти требуемый контроллер или передатьnullфункцииlinkпри отсутствии. -
^— Поиск требуемого контроллера путём поиска в элементе и его родителях. Выбрасывает ошибку, если не найден. -
^^— Поиск требуемого контроллера путём поиска в родителях элемента. Выбрасывает ошибку, если не найден. -
?^— Попытка найти требуемый контроллер путём поиска в элементе и его родителях или передать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 -->
templateNamespace
Строка, представляющая тип документа, используемый разметкой в шаблоне. AngularJS нуждается в этой информации, так как эти элементы должны создаваться и клонироваться особым способом, когда они определены вне своих обычных контейнеров, таких как <svg> и <math>.
-
html- Все корневые узлы в шаблоне являются HTML. Корневые узлы также могут быть элементами верхнего уровня, такими как<svg>или<math>. -
svg- Корневые узлы в шаблоне являются элементами SVG (исключая<math>). -
math- Корневые узлы в шаблоне являются элементами MathML (исключая<svg>).
Если templateNamespace не указан, то пространство имен считается html.
шаблон
HTML-разметка, которая может:
- Заменить содержимое элемента директивы (по умолчанию).
- Заменить сам элемент директивы (если
replaceравно true - УСТАРЕЛО). - Оборачивает содержимое элемента директивы (если
transcludeравно true).
Значение может быть:
- Строкой. Например,
<div red-on-hover>{{delete_str}}</div>. - Функцией, которая принимает два аргумента
tElementиtAttrs(описаны в функции APIcompileниже) и возвращает строковое значение.
templateUrl
Это похоже на template, но шаблон загружается из указанного URL-адреса асинхронно.
Поскольку загрузка шаблона асинхронна, компилятор приостановит компиляцию директив в этом элементе до тех пор, пока шаблон не будет разрешен. Тем временем он продолжит компиляцию и привязку элементов-собратьев и родительских элементов так, как если бы в этом элементе не было никаких директив.
Компилятор не приостанавливает всю компиляцию, ожидая загрузки шаблонов, так как это приведет к "зависанию" всего приложения до тех пор, пока все шаблоны не будут загружены асинхронно — даже в том случае, когда только одна глубоко вложенная директива имеет templateUrl.
Загрузка шаблона асинхронна даже если шаблон был предварительно загружен в $templateCache
Вы можете указать templateUrl как строку, представляющую URL-адрес, или как функцию, которая принимает два аргумента tElement и tAttrs (описаны в функции API compile ниже) и возвращает строковое значение, представляющее URL-адрес. В любом случае URL-адрес шаблона передаётся через $sce.getTrustedResourceUrl.
replace ([УСТАРЕЛО!], будет удалено в следующей основной версии - т.е. v2.0)
указать, что должен заменить шаблон. По умолчанию false.
-
true- шаблон заменит элемент директивы. -
false- шаблон заменит содержимое элемента директивы.
Процесс замены мигрирует все атрибуты/классы из старого элемента в новый. См. Руководство по директивам для примера.
Существует очень мало случаев, когда замена элементов необходима для функционирования приложения, основным из которых является повторное использование пользовательских компонентов, используемых в контексте SVG (потому что SVG не работает с пользовательскими элементами в дереве DOM).
transclude
Извлечь содержимое элемента, где появляется директива, и сделать его доступным для директивы. Содержимое компилируется и предоставляется директиве как функция **трансклюзии**. См. раздел **Трансклюзия** ниже.
Существует два типа трансклюзии в зависимости от того, хотите ли вы трансклюдировать только содержимое элемента директивы или весь элемент:
-
true- трансклюдировать содержимое (т.е. дочерние узлы) элемента директивы. -
'element'- трансклюдировать весь элемент директивы, включая любые директивы в этом элементе, которые определены с более низким приоритетом, чем эта директива. При использовании свойствоtemplateигнорируется.
compile
function compile(tElement, tAttrs, transclude) { ... }
Функция compile занимается преобразованием шаблона DOM. Поскольку большинство директив не выполняют преобразование шаблона, она используется не часто. Функция compile принимает следующие аргументы:
-
tElement- элемент шаблона - Элемент, где была объявлена директива. Безопасно выполнять преобразования шаблона только на элементе и его дочерних элементах. -
tAttrs- атрибуты шаблона - Нормализованный список атрибутов, объявленных в этом элементе, общий для всех функций компиляции директив. -
transclude- [УСТАРЕЛО!] Функция привязки трансклюзии:function(scope, cloneLinkingFn)
template или templateUrl объявления или ручную компиляцию внутри функции compile.transclude, передаваемая функции compile, устарела, так как, например, она не знает правильной внешней области видимости. Пожалуйста, используйте функцию трансклюзии, передаваемую функции link.Функция compile может иметь возвращаемое значение, которое может быть либо функцией, либо объектом.
-
возвращение функции (post-link) - эквивалентно регистрации функции привязки через свойство
linkобъекта конфигурации, когда функция compile пуста. -
возвращение объекта с зарегистрированными функциями через свойства
preиpost- позволяет управлять вызовом функции привязки во время фазы привязки. См. информацию о функциях предварительной и последующей привязки ниже.
link
Это свойство используется только в том случае, если свойство compile не определено.
function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
Функция link отвечает за регистрацию обработчиков событий DOM и обновление DOM. Она выполняется после клонирования шаблона. Именно здесь будет размещена большая часть логики директивы.
-
scope- Область видимости - Область видимости, используемая директивой для регистрации наблюдений. -
iElement- элемент экземпляра - Элемент, где используется директива. Безопасно манипулировать дочерними элементами элемента только в функцииpostLink, так как дочерние элементы уже были привязаны. -
iAttrs- атрибуты экземпляра - Нормализованный список атрибутов, объявленных в этом элементе, общий для всех функций привязки директив. -
controller- экземпляр(ы) требуемого контроллера директивы - Экземпляры разделяются между всеми директивами, что позволяет директивам использовать контроллеры в качестве канала связи. Точное значение зависит от свойстваrequireдирективы:-
string: экземпляр контроллера -
array: массив экземпляров контроллеров - не требуется контроллер(ы):
undefined
Если требуемый контроллер не найден, а он является необязательным, экземпляр
null, в противном случае выбрасывается ошибка Отсутствующий требуемый контроллер. -
-
transcludeFn- функция привязки трансклюзии, предварительно привязанная к правильной области видимости трансклюзии. Это то же самое, что и параметр$transcludeконтроллеров директив, см. там детали.function([scope], cloneLinkingFn, futureParentElement).
Функция предварительной привязки
Выполняется до привязки дочерних элементов. Небезопасно выполнять преобразование DOM, так как функция привязки компилятора не сможет найти правильные элементы для привязки.
Функция последующей привязки
Выполняется после привязки дочерних элементов.
Обратите внимание, что дочерние элементы, содержащие директивы templateUrl , не будут скомпилированы и привязаны, так как они ожидают асинхронной загрузки своего шаблона, и их собственная компиляция и привязка приостановлены до тех пор, пока это не произойдёт.
Безопасно выполнять преобразование DOM в функции последующей привязки для элементов, которые не ждут разрешения своих асинхронных шаблонов.
Трансклюзия
Трансклюзия — это процесс извлечения набора элементов DOM из одной части DOM и копирования их в другую часть DOM, сохраняя их связь с исходной областью видимости AngularJS, из которой они были взяты.
Трансклюзия используется (часто с ngTransclude) для вставки исходного содержимого элемента директивы в указанное место в шаблоне директивы. Преимущество трансклюзии перед простым ручным перемещением элементов DOM заключается в том, что трансклюдированное содержимое имеет доступ к свойствам области видимости, из которой оно было взято, даже если у директивы изолированная область видимости. См. Руководство по директивам.
Это позволяет виджету иметь частное состояние для своего шаблона, а трансклюдированному содержимому получить доступ к его исходной области видимости.
Функции трансклюзии
Когда директива запрашивает трансклюзию, компилятор извлекает её содержимое и предоставляет функцию **трансклюзии** функции link и controller. Эта функция трансклюзии — это специальная **функция привязки**, которая вернёт скомпилированное содержимое, привязанное к новой области видимости трансклюзии.
ngTransclude, то вам не нужно беспокоиться об этой функции, так как ngTransclude позаботится об этом за вас.Если вы хотите вручную управлять вставкой и удалением транклюдированного содержимого в вашем директиве, то вы должны использовать эту функцию транклюзии. Когда вы вызываете функцию транклюзии, она возвращает объект jqLite/JQuery, содержащий скомпилированную DOM-структуру, которая связана с правильной областью транклюзии.
Когда вы вызываете функцию транклюзии, вы можете передать функцию клонирования и привязки. Эта функция принимает два параметра, function(clone, scope) { ... }, где clone — это свежая скомпилированная копия вашего транклюдированного содержимого, а scope — это новая созданная область транклюзии, к которой привязано клонированное содержимое.
Обычно, транклюдированное содержимое (clone) прикрепляется к DOM внутри функции клонирования и привязки:
var transcludedContent, transclusionScope;
$transclude(function(clone, scope) {
element.append(clone);
transcludedContent = clone;
transclusionScope = scope;
});
Позже, если вы хотите удалить транклюдированное содержимое из DOM, вы также должны уничтожить связанную область транклюзии:
transcludedContent.remove(); transclusionScope.$destroy();
element.remove() для удаления), то вы также несете ответственность за вызов $destroy для области транклюзии. Встроенные директивы для манипулирования DOM, такие как ngIf, ngSwitch и ngRepeat автоматически уничтожают свои клоны транклюдированного содержимого по мере необходимости, поэтому вам не нужно беспокоиться об этом, если вы просто используете ngTransclude для вставки транклюзии в ваш директиву.
Области транклюзии
Когда вы вызываете функцию транклюзии, она возвращает фрагмент DOM, предварительно привязанный к области транклюзии. Эта область является дочерней по отношению к области директивы (и поэтому уничтожается при уничтожении области директивы), но наследует свойства из области, из которой была взята.
Например, рассмотрим директиву, использующую транклюзию и изолированную область. Иерархия DOM может выглядеть так:
<div ng-app>
<div isolate>
<div transclusion>
</div>
</div>
</div>
Иерархия областей $parent будет выглядеть так:
- $rootScope - isolate - transclusion
но области будут наследоваться прототипно из разных областей до своих $parent.
- $rootScope - transclusion - isolate
Атрибуты
Объект Атрибуты — передается в качестве параметра в функциях 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=) | функция, доступная для директив — УСТАРЕЛА. Примечание: Передача функции transclude в функцию $compile устарела, поскольку она, например, не будет использовать правильную внешнюю область. Пожалуйста, передайте функцию transclude в качестве parentBoundTranscludeFn функции link вместо этого. |
| maxPriority | number | применять только директивы с приоритетом ниже заданного (только влияет на корневой(ые) элемент(ы), а не на их потомков) |
Возвращаемое значение
function(scope, cloneAttachFn=, options=) |
функция link, которая используется для привязки шаблона (элемента/дерева DOM) к области. Где:
Вызов функции связывания возвращает элемент шаблона. Это либо исходный элемент, переданный в функцию, либо клон элемента, если После связывания, отображение не обновляется до вызова $digest, который обычно выполняется Angular автоматически. Если вам нужен доступ к связанному представлению, есть два способа:
Подробную информацию о работе компилятора см. в разделе «Компилятор Angular HTML» руководства для разработчиков. |
© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.3.20/docs/api/ng/service/$compile