В настоящее время я пишу несколько директив Angular, которые меняют свои шаблоны в зависимости от определенных атрибутов. Они выглядят структурно так:
app.directive('mydir', function ($compile) {
return {
restrict: 'E',
replace: true,
transclude: true,
compile: function (elem, attrs, transclude) {
var replacement;
// operations
return function (scope, lElem, lAttrs) {
transclude(scope, function (clone, scope) {
// more operations
});
elem.replaceWith($compile(replacement)(scope)); // IMPORTANT
};
}
};
});
и находятся на этом Plunkr. Теперь, как написано (хорошо, сфокусировано), эти директивы не работают, если вы пытаетесь их вложить. Внутренняя директива заканчивается тем, что ее полностью исключенные элементы. Однако, если я заменил elem.replaceWith(...)
на lElem.replaceWith(...)
(в строке 36 файла Javascript в Plunkr), все будет в порядке, и я могу вложить столько раз, сколько захочу. Почему это происходит? В чем тут разница? Я понимаю, что elem
не скомпилирован и lElem
есть, но что это значит и как это влияет на мой код? Кроме того, разве не обескураживают манипуляции с DOM в функции link
?
Что я пробовал. Я попытался отлаживать это сам, и похоже, что для внутренней директивы функция компиляции вызывается дважды (я бы предположил, что один раз из любого Angular и один раз с того момента, когда я использую $compile
на нем), при первом компиляции все правильно, а во второй раз все неправильно. Но я не могу заставить его компилировать один раз, не удаляя инструкцию $compile
, которая нарушает все! Похоже, что Angular скомпилирует все "на обратном пути" (то есть сначала детей) и связывает все "по пути вниз" (то есть родители сначала), но я не могу это подтвердить. По подозрению я попытался вернуть функцию prelink вместо функции postlink, но безрезультатно. Я также попытался поставить вызов elem.replaceWith(...)
перед функцией link
и скомпилировать дочерние элементы внутри функции link
, но это тоже не сработало.
Что я думаю, что происходит. Я полагаю, что включение функции пересылки в функцию ссылок приводит к запутыванию всего (хотя я вынужден, потому что compile
не имеет области видимости), принимая старый клон внутри директива и по какой-либо причине удалять ее дочерние элементы (elem
и lElem
, например, не имеют детей). Я не уверен, как подтвердить это или как его исправить, как только он подтвердится. Я предварительно провел некоторое тестирование, введя $rootScope
и выполнив все ссылки и т.д. В функции компиляции, и ничего не получилось. Я не уверен, есть ли какие-либо различия между компиляцией и компиляцией с областью содержимого.