私は現在、渡された特定の属性に応じてテンプレートを変更するいくつかの 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にあります。さて、書かれているように(まあ、肉付けされています)、これらのディレクティブをネストしようとすると機能しません。内部ディレクティブは、トランスクルージョンされた要素が完全に消去された状態になります。ただし、(Plunkr の Javascript ファイルの 36 行目) を置き換えるelem.replaceWith(...)
とlElem.replaceWith(...)
、すべて問題なく、何度でもネストできます。なぜこうなった?ここでの違いは何ですか?elem
コンパイルされていないことは理解してlElem
いますが、それは実際には何を意味し、コードにどのように影響しますか? さらに、link
関数内で DOM 操作を行うのはお勧めできませんか?
私が試したこと。私はこれを自分でデバッグしようとしましたが、内部ディレクティブの場合、コンパイル関数が2回呼び出されているように見えます(angularが行っていることから1回、$compile
それを使用したときから1回と仮定します)、最初にすべてをコンパイルしますは正しく、2 回目はすべてが間違っています。しかし、ステートメントを削除せずに一度だけコンパイルすることはできません。これにより、$compile
すべてが壊れます。また、Angular は「上に向かって」(つまり子を最初に) すべてをコンパイルし、「下へ」 (つまり親を最初に) すべてをリンクしているように見えますが、それを確認することはできません。直感で、postlink 関数の代わりに prelink 関数を返そうとしましたが、役に立ちませんでした。私'elem.replaceWith(...)
link
link
機能しますが、それも機能しませんでした。
私が思うことは起こっています。トランスクルージョンをリンク関数に入れることは、ディレクティブ内の古いクローンを取得し、何らかの理由でその子を削除することによってすべてを台無しにしていると思います(ただしcompile
、スコープがないため強制されます) (参照されたときに子がありません。実例)。これを確認する方法、または確認された後に修正する方法がわかりません。コンパイル機能ですべてのリンクなどを挿入して実行することにより、事前にいくつかのテストを行いましたが、何も機能しませんでした。ただし、それをコンパイルすることと子スコープでコンパイルすることの間に違いがあるかどうかはわかりません。elem
lElem
$rootScope