我正在寻找写两个角度指令,一个父指令和一个子指令,以创建可排序和可克隆的小部件。预期的标记是:
<div class="widget-container" data-sortable-widgets> <section class="widget" data-cloneable-widget></section> <div>
但是,子指令似乎在父元素之前,某个元素可用之前执行(子元素由父元素添加):
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(),它的工作方式正相反- 我们可以利用它来受益。
postLink()
link()
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
看吧live on plunker。
live on 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 } } }; }
$compile
顺便说一句,您是正确的- priority打算与共享相同元素的指令一起使用。
priority
angular.noop只是一个空方法,什么也不返回。如果仍然要使用这些postLink()函数,请像通常那样放置函数声明,即:
angular.noop
post: function postLink(scope, iElement, iAttrs, controller) { ... }
谨防使用templateUrl,例如 “由于模板加载是异步的 , 因此在加载模板之前,将暂停编译/链接” [源代码]。结果,执行顺序将被破坏。您可以通过包括在template属性中内联的模板来解决此问题。
templateUrl
template