Javascript 确认按钮事件触发两次

Javascript 确认按钮事件触发两次,javascript,jquery,angularjs,Javascript,Jquery,Angularjs,所以我有一个确认按钮: <confirm-button class-name="btn-primary" text="Save" body="A customer with the same Last Name is already associated with this Company. Do you want to create this customer anyway?" action

所以我有一个确认按钮:

<confirm-button class-name="btn-primary" 
                text="Save"
                body="A customer with the same Last Name is already associated with this Company. Do you want to create this customer anyway?"
                action="vm.save(false)"
                place="bottom"></confirm-button>

这是一个自定义指令:

.directive('confirmButton', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            text: '@',
            className: '@',
            action: '&'
        },
        controller: function ($scope, $element, $attrs) {
            var content = $attrs.body ? '<p>' + $attrs.body + '</p>' : '';
            var place = $attrs.place ? $attrs.place : 'top';

            var rndEleId = 'BtnId' + Math.random().toString(36).slice(2);

            var popoverOpts = {
                title: $attrs.title || 'Are you sure?',
                placement: place,
                html: true,
                content: content +
                    '<div class="centered">' +
                    '<button id="yes' + rndEleId + '" name="yes' + rndEleId + '" type="button" class="btn btn-primary btn-small" data-result="yes"><i class="icon-ok"></i> Yes</button>' +
                    '&nbsp;' +
                    '<button id="no' + rndEleId + '" name="no' + rndEleId + '" type="button" class="btn btn-warning btn-small" data-result="no"><i class="icon-ban-circle"></i> No</button>' +
                    '</div>'
            };

            $element.popover(popoverOpts)
                .parent()
                .delegate('button',
                    'click',
                    function(e) {
                        e.preventDefault();

                        var el = $(e.currentTarget);
                        var result = el.data('result');

                        $element.popover('hide');

                        if (result === 'yes') {
                            $scope.$apply($scope.action);
                        }
                    }
                );
        },
        template: '<a href="" class="btn {{className}}">{{text}}</a>'
    };
})
指令('confirButton',函数(){ 返回{ 限制:'E', 替换:正确, 范围:{ 正文:“@”, 类名:“@”, 行动:'&' }, 控制器:函数($scope、$element、$attrs){ var content=$attrs.body?''+$attrs.body+'

':''; 变量位置=$attrs.place?$attrs.place:'top'; var rndEleId='BtnId'+Math.random().toString(36).slice(2); 变量popoverOpts={ title:$attrs.title | |“你确定吗?”, 地点:地点,, 是的, 内容:内容+ '' + “是的”+ ' ' + “不”+ '' }; $element.popover(popoverOpts) .parent() .delegate('按钮', “点击”, 职能(e){ e、 预防默认值(); var el=$(e.currentTarget); var结果=el.数据(“结果”); $element.popover('hide'); 如果(结果==‘是’){ $scope.$apply($scope.action); } } ); }, 模板:“” }; }) 我在页面上有两个按钮:一个在页面顶部,一个在底部。无论单击哪一个按钮,当单击“是”或“否”按钮时,它们都会触发两次。这意味着按钮操作属性中的Save方法将被调用两次。如果你正在更新一个记录,这不是一件可怕的事情,但是如果你正在创建一个记录。。。它被创建了两次

我使用了Chrome的开发工具,并在
e.preventDefault()上放置了一个断点指令中的行,而且确实,它会被命中两次

但只有当页面上使用了多个指令时,才会发生这种情况。如果我只有一个按钮(在页面的顶部或底部),则
e.preventDefault()断点只命中一次。此外,它似乎是多线程的。我在某一点上加入了一个反变量,使用了老派的理论“将其设置为0,然后将其设置为++,然后检查它现在是否为1。如果它大于1,则不执行该操作。如果它等于1,则执行该操作。”变量。。。每次都是新创建的,因此不会增加到1以上


我被难住了。

您并没有真正提出一个直接的问题,但您似乎想知道为什么会发生这种情况。

之所以发生这种情况,是因为每次加载指令时,您都要向指令的父级添加一个单击事件侦听器。因此,当您在同一页面上有两个指令时,您单击了按钮,事件被触发两次,因为注册了两个事件侦听器。此处是使用以下方法注册事件侦听器的位置:

首先,当指令被破坏时,您需要确保自己进行清理,并解除事件侦听器的绑定(请查看文档)。下面是一个快速示例,说明在指令get被破坏时如何解除事件侦听器的绑定:

// ...

// register your popover here
$element.popover(popoverOpts);

// reference your parent
var parent = $element.parent();

// reference your click function
var handleClick = function(e) {
    e.preventDefault();

    var el = $(e.currentTarget);
    var result = el.data('result');

    $element.popover('hide');

    if (result === 'yes') {
        $scope.$apply($scope.action);
    }
}

// register your event listener
parent.on('click', handleClick);

// when your directive get's destroyed you need to unbind the `handleClick` function
$scope.$on('$destroy', function(e) {
    parent.off('click', handleClick);
});

// ...
要解决您的问题,您需要确保您正在注册事件侦听器以满足您的需要。您可以阅读有关事件侦听器的更多信息


虽然说实话,看看你的代码,你应该试一试。

不确定你是否知道,但是有一个popover()的本机实现。如果你提供一个带有复制错误的JSFIDLE或PLUNK,找到解决方案可能会更容易。@Alon Eitan-实际上,这就是指令中的内容。它从Angular开始使用popover实现,并将其扩展为确认对话框。@PKD Cool,请注意,您可以使用自定义模板(在示例中)实现它,并且可以使用
ngClick
将单击事件绑定到按钮Bootstrap 2.3.2是否存在相同的popover实现?遗憾的是,我现在无法升级应用程序中的引导版本。“为什么”正是我希望回答的问题。另外,我使用的是Bootstrap,但是2.3.2(有一个很长很长的故事,关于为什么网站不在最新版本上,但这需要很长时间才能进入)没有以一种令人愉快的方式处理事情。这很好,不使用ui Bootstrap没有什么错,只要确保你清理了你的侦听器,否则你会有内存泄漏。我在你的代码中注意到你丢失了“popoverOpts”。。。这些选项是如何进入你的POPORE的?你仍然需要传递你的POPopOPT,你可以单独做或者将它链接到 var父= $Eng.PopOver(POPOUPopts)PARTRONE()中;代码>-我已经更新了上面的答案以包含该部分
// ...

// register your popover here
$element.popover(popoverOpts);

// reference your parent
var parent = $element.parent();

// reference your click function
var handleClick = function(e) {
    e.preventDefault();

    var el = $(e.currentTarget);
    var result = el.data('result');

    $element.popover('hide');

    if (result === 'yes') {
        $scope.$apply($scope.action);
    }
}

// register your event listener
parent.on('click', handleClick);

// when your directive get's destroyed you need to unbind the `handleClick` function
$scope.$on('$destroy', function(e) {
    parent.off('click', handleClick);
});

// ...