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

Dr_*_*Sam 15 angularjs angularjs-directive

AngularJS中(前/后)链接函数的时序在文档中有明确定义

预连接功能

在子元素链接之前执行.由于编译器链接功能无法找到正确的链接元素,因此进行DOM转换是不安全的.

后连接功能

链接子元素后执行.在链接后功能中进行DOM转换是安全的.

这篇博客文章清楚地说明了这个预期的顺序.

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

这是一个直观元素的例子(参见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>
Run Code Online (Sandbox Code Playgroud)

吊坠看起来像

dropright

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

预期

但有时(几次刷新后),订单不符合预期:

有时候会发生

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

这可能是因为,在我的特殊情况下,我在儿童指令中调用了直接控制器(参见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;
});
Run Code Online (Sandbox Code Playgroud)

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

bha*_*tol 15

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

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

带有模板而不是templateUrl的Plunker

我不假装完全理解compile.js代码.然而,似乎在 compileTemplateUrl函数中 $http.success()解析模板然后在成功时applyDirectivesToNode函数被称为传入postLinkFn.

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