在编译期间注入指令时,为什么鼠标单击父级会触发两次

时间:2015-04-05 22:38:33

标签: angularjs ionic-framework

我有一个指令需要插入一个额外的指令依赖 关于一些模型价值。我在指令的[编辑]预链接阶段这样做。 parent指令设置了一个主机 孩子使用的方法和数据。因此,我有儿童指令 scope:true

在外部(或父项)指令上有一个单击处理程序方法。当我 点击这个,它会被解雇两次。我想知道为什么以及如何。现在的 只有这样我知道如何阻止它是通过调用event::stopImmediatePropagation() 但我怀疑我在这里做错了什么。

模板用法

<dashboard-box data-box-type="column with no heading">
    <div class="card">
        <div 
                ng-click="show($event)" 

                class="box-title item item-divider ng-binding is-shown" 
                ng-class="{'is-shown':showMe}">
            <span class="box-title-string ng-binding">A/R V1</span>
        </div>
        <div class="box-content item item-text-wrap" ng-show="showMe">
            <!-- plug appropriate dashbox here - in dashboard-box compile -->
            <dashbox-column-with-no-heading>
                <div>
                    SOME DATA...
                </div>
            </dashbox-column-with-no-heading>
        </div>
    </div>
</dashboard-box>

在仪表板框的指令中:

scope: {
    boxType: "@"
},
pre: function preLink(scope, iElement, iAttrs, controller) {
    // some crazy hardcoding - because find by tagname...replaceWith throws in ionic
    var parent_div = angular.element(angular.element(iElement.children()[0]).children()[1]);
    if (!parent_div) {
        return; // programmer error in template??
    }
    var html_tag_name = d_table_type_to_directive_name.xl[iAttrs.boxType];
    parent_div.append(angular.element( "<" + html_tag_name + ">" ));
    $compile(iElement.contents())(scope); // angular idiom
}

在仪表板框的控制器中:

$scope.show = function($e){
    $log.log("dashboard box show(), was=", $scope.showMe, $e);

    if ($e) $e.stopImmediatePropagation(); // <<<<<<<<<<< without this, double-hits!!

    $scope.showMe = ! $scope.showMe;
    // etc
};

在dashbox-column-with-row-heading的指令中:

restrict: "E",
scope: true,
templateUrl: "dashbox-column-with-row-heading.tpl.html"
controller: function(){
    // specialized UI for this directive
}

我正在使用ionicframework rc-1.0.0和angularjs 1.3.13。

1 个答案:

答案 0 :(得分:4)

这里发生的是你正在双重编译/链接ng-click指令:1)Angular第一次在编译阶段做到这一点 - 它遍历DOM并编译指令,首先是{{1} },然后它的子节点,以及dashboardBox)和2) - 当您使用ngClick进行编译时。

这是一个简化的示例 - demo - 可以重现您的问题:

$compile(element.contents())(scope)

并且<foo> <button ng-click="doFoo()">do foo</button> </foo> 指令是:

foo

您需要做的是转换内容。通过转换,Angular在编译指令时编译内容,并通过.directive("foo", function($compile) { return { scope: true, link: { pre: function(scope, element, attrs, ctrls, transclude) { $compile(element.contents())(scope); // second compilation scope.doFoo = function() { console.log("foo called"); // will be called twice }; } } }; }); 函数使内容可用。

所以,不要再使用transclude,而是使用已编译的 - 但尚未链接(直到你告诉它应该链接到什么) - 指令的内容。

使用下面的$compile示例,情况如下:

foo