1. ホーム
  2. javascript

[解決済み] Angularディレクティブの再帰性

2022-04-21 03:50:28

質問

再帰的なアンギュラーディレクティブのQ&Aはいくつかありますが、それらはすべて次の解決策の一つに帰結します。

最初の1枚 は、手動でのコンパイルプロセスを理解しやすく管理しない限り、以前にコンパイルされたコードを削除できないという問題があります。 第二のアプローチ しかし、もっと緊急な問題は、ディレクティブと同じようにパラメータを設定することができないことです。

私は、手動で angular.bootstrap または @compile() をリンク関数に追加する必要がありますが、これでは削除する要素と追加する要素を手動で追跡する問題が残ります。

実行時の状態を反映するために、要素の追加/削除を管理するパラメータ化された再帰的パターンを持つ良い方法はないでしょうか?つまり、追加/削除のノードボタンと、その値がノードの子ノードに渡される入力フィールドを持つツリーです。おそらく、2番目のアプローチと連鎖したスコープ(しかし、私はこれを行う方法がわからない)を組み合わせたものでしょうか?

解決方法は?

dnc253 さんのスレッドに書かれている解決策に触発され、再帰機能を抽象化しました。 サービス .

module.factory('RecursionHelper', ['$compile', function($compile){
    return {
        /**
         * Manually compiles the element, fixing the recursion loop.
         * @param element
         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
         * @returns An object containing the linking functions.
         */
        compile: function(element, link){
            // Normalize the link parameter
            if(angular.isFunction(link)){
                link = { post: link };
            }

            // Break the recursion loop by removing the contents
            var contents = element.contents().remove();
            var compiledContents;
            return {
                pre: (link && link.pre) ? link.pre : null,
                /**
                 * Compiles and re-adds the contents
                 */
                post: function(scope, element){
                    // Compile the contents
                    if(!compiledContents){
                        compiledContents = $compile(contents);
                    }
                    // Re-add the compiled contents to the element
                    compiledContents(scope, function(clone){
                        element.append(clone);
                    });

                    // Call the post-linking function, if any
                    if(link && link.post){
                        link.post.apply(null, arguments);
                    }
                }
            };
        }
    };
}]);

これは、以下のように使用されます。

module.directive("tree", ["RecursionHelper", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {family: '='},
        template: 
            '<p>{{ family.name }}</p>'+
            '<ul>' + 
                '<li ng-repeat="child in family.children">' + 
                    '<tree family="child"></tree>' +
                '</li>' +
            '</ul>',
        compile: function(element) {
            // Use the compile function from the RecursionHelper,
            // And return the linking function(s) which it returns
            return RecursionHelper.compile(element);
        }
    };
}]);

こちらをご覧ください プランカー をデモでご覧ください。 私はこのソリューションが一番好きです。

  1. 特別なディレクティブが必要ないため、htmlがきれいにならない。
  2. 再帰処理ロジックはRecursionHelperサービスに抽象化されているため、ディレクティブをすっきりさせることができます。

更新しました。 Angular 1.5.xでは、もうトリックは必要ありません。 テンプレート とは併用できません。 テンプレートウル