为什么在转换子链接功能之前执行了帖子链接功能?

时间:2014-08-11 10:37:27

标签: angularjs angularjs-directive

AngularJS中(前/后)链接函数的时序在the documentation

中有明确定义
  

预连接功能

     

在链接子元素之前执行。做DOM不安全   转换,因为编译器链接功能将无法定位   正确的链接元素。

     

后期关联功能

     

链接子元素后执行。做DOM是安全的   转换后的连接功能。

this blog post清楚地说明了这种预期的顺序。

但是当使用ng-transclude和嵌套指令时,这个顺序似乎不适用。

以下是一个直观元素的示例( See the Plunkr

<!-- index.html -->
<dropright>
  <col1-item name="a">
    <col2-item>1</col2-item>
    <col2-item>2</col2-item>
  </col1-item>
  <col1-item name="b">
    ...
  </col1-item>
</dropright>

// dropright-template.html
<div id="col1-el" ng-transclude></div>
<div id="col2-el">
  <!-- Only angularJS will put elements in there -->
</div>

// col1-item-template.html
<p ng-transclude></p>

// col2-item-template.html
<div ng-transclude></div>

dropright看起来像

dropright

当调用链接和控制器函数时,指令在控制台中写入日志。 它通常显示:

expected

但有时(经过几次刷新后),订单并不像预期的那样:

sometimes happen

dropright post-link函数在其子项的post-link函数之前执行。

这可能是因为,在我的特定情况下,我在儿童指令( See the Plunkr )中调用了直接控制器

angular.module('someApp', [])

.directive('dropright', function() {
    return {
        restrict: 'E',
        transclude: 'true',
        controller: function($scope, $element, $attrs) {
            console.info('controller - dropright');

            $scope.col1Tab = [];
            $scope.col2Tab = [];

            this.addCol1Item = function(el) {
                console.log('(col1Tab pushed)');
                $scope.col1Tab.push(el);
            };

            this.addCol2Item = function(el) {
                console.log('(col2Tab pushed)');
                $scope.col2Tab.push(el);
            };
        },
        link: {
            post: function(scope, element, attrs) {
                console.info('post-link - dropright');
                // Here, I want to move some of the elements of #col1-el
                // into #col2-el
            }
        },
        templateUrl: 'dropright-tpl.html'
    };
})

.directive('col1Item', function($interpolate) {
    return {
        require: '^dropright',
        restrict: 'E',
        transclude: true,
        controller: function() {
            console.log('-- controller - col1Item');
        },
        link: {
            post: function(scope, element, attrs, droprightCtrl) {
                console.log('-- post-link - col1Item');
                droprightCtrl.addCol1Item(element.children()[0]);
            }
        },
        templateUrl: 'col1-tpl.html'
    };      
})

.directive('col2Item', function() {
    var directiveDefinitionObject = {
        require: '^dropright',
        restrict: 'E',
        transclude: true,
        controller: function() {
            console.log('---- controller - col2Item');
        },
        link: {
            post: function(scope, element, attrs, droprightCtrl) {
                console.log('---- post-link - col2Item');
                droprightCtrl.addCol2Item(element.children()[0]);
            }
        },
        templateUrl: 'col2-tpl.html'
    };
    return directiveDefinitionObject;
});

在使用翻译时,是否有任何干净的方法在其子项的所有链接功能之后执行指令的链接功能?

2 个答案:

答案 0 :(得分:15)

这是我的理论 - 它不是导致序列问题的转换方面,而是模板是templateUrl。在post link函数对它进行操作之前,需要解析模板 - 因此我们说post链接函数可以安全地进行DOM操作。虽然我们为所有3个模板获得304s - 但我们必须阅读它们并最终解决模板承诺。

我用模板而不是templateUrl创建了一个plunker来证明推论。我有热点刷新/关闭多次停止/运行,但我总是得到link - dropright

Plunker with template instead of templateUrl

我不假装完全理解compile.js代码。然而它确实出现在  compileTemplateUrl函数$http.success()解析模板,然后成功调用applyDirectivesToNode函数传入postLinkFn

https://github.com/angular/angular.js/blob/master/src/ng/compile.js

答案 1 :(得分:0)

这可能只是与Plunker的怪异。我尝试将文件复制到本地IIS,但无法复制问题。