簡體   English   中英

如何在子指令之前執行父指令?

[英]How to execute parent directive before child directive?

我正在尋找兩個角度指令,一個父指令和一個子指令,來創建可排序和可復制的小部件。 預期的標記是:

<div class="widget-container" data-sortable-widgets>
      <section class="widget" data-cloneable-widget></section>
<div>

但是,child指令似乎在父元素之前執行,在某個元素可用之前(由父元素添加):

function SortableWidgetsDirective() {
    return {
        priority: 200,
        restrict: 'A',
        link: function ($scope, element, attrs) {
            element.find(".widget header").append($("<div class='widget-controls'></div>"));
            element.sortable({  });
        }
    };
}

function CloneableWidgetDirective() {
    return {
        priority: 100,
        restrict: 'A',
        link: function ($scope, element, attrs) {
            // This directive wrongfully executes first so widget-controls is no available
            element.find("header .widget-controls").append($("<div class='clone-handle'></div>"));
        }
    };
}

正如你所看到我嘗試設置優先級但我認為因為它們在不同的元素上,它不起作用。

如何讓父項先執行?

推理

postLink()以相反的順序執行,這意味着子指令的postLink()將在父級之前調用(即深度優先)。 出於某種原因,這是默認行為( link()實際上是指postLink() )。 幸運的是,我們還有preLink() ,它以相反的方式工作 - 我們可以利用它來實現我們的利益。

為了說明這一點 - 以下代碼片段:

app.directive('parent', function($log) {
    return {
        restrict: 'E',
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {
                    $log.info('parent pre');
                },
                post: function postLink(scope, iElement, iAttrs, controller) {
                    $log.info('parent post');
                }
            }
        }
    };
});

app.directive('child', function($log) {
    return {
        restrict: 'E',
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {
                    $log.info('child pre');
                },
                post: function postLink(scope, iElement, iAttrs, controller) {
                    $log.info('child post');
                }
            }
        }
    };
});

...將輸出以下內容:

> parent pre
> child pre
> child post
> parent post 

在plunker上看到它。

如果我們希望在子代之前執行父指令的邏輯,我們將顯式使用preLink()

function SortableWidgetsDirective() {
    return {
        restrict: 'A',
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {
                    iElement.find(".widget header").append($("<div class='widget-controls'></div>"));
                    iElement.sortable({});
                },
                post: angular.noop
            }
        }
    };
}

function CloneableWidgetDirective() {
    return {
        restrict: 'A',
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                pre: function preLink(scope, iElement, iAttrs, controller) {
                    iElement.find("header .widget-controls").append($("<div class='clone-handle'></div>"));
                },
                post: angular.noop
            }
        }
    };
}

參考

  • AngularJS文檔上的$compile服務。

Post Scriptum

  • 順便說一下,你是正確的 - priority意味着與共享相同元素的指令一起使用。

  • angular.noop只是一個不返回任何內容的空方法。 如果您仍想使用postLink()函數,只需放置函數聲明,就像通常那樣,即:

     post: function postLink(scope, iElement, iAttrs, controller) { ... } 
  • 使用templateUrl ,因為“因為模板加載是異步的,所以編譯/鏈接被掛起,直到加載模板” [source] 結果,執行順序將被中斷。 您可以通過在template屬性中包含內聯模板來解決此問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM