所以我有一个确认按钮:
<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>' +
' ' +
'<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>'
};
})
这个按钮在页面上有两次:一次在页面顶部,一次在底部。无论您单击哪一个,当单击"is"或“否”按钮时,它们都会触发两次。这意味着按钮 Action 属性中的 Save 方法被调用两次。如果您要更新一条记录,这并不是一件可怕的事情,但如果您要创建一条记录......它会创建两次。
我使用了 Chrome 的开发者工具,并在指令中的 e.preventDefault();
行上放置了一个断点,果然,它被命中了两次。
但是只有当页面上使用了多个指令时才会发生这种情况。如果我只有一个按钮(位于页面顶部或底部),则 e.preventDefault();
断点只会被命中一次。此外,它似乎是多线程的。我在某个时刻放入了一个计数器变量,按照旧派理论“将其设置为 0,然后将其设置为++,然后检查它现在是否为 1。如果它大于 1,则不执行该操作.如果等于1,则执行该操作。”而且变量...每次都是新创建的,因此增量永远不会超过 1。
我被困住了。
最佳答案
您并没有真正提出直接问题,但您似乎想知道为什么会发生这种情况。
发生这种情况是因为您每次加载指令时都向该指令的父级添加了一个点击事件监听器。因此,当您在同一页面上有两个这样的指令时,您单击了按钮,并且该事件被触发两次,因为注册了 2 个事件监听器。您可以在此处使用 delegate
注册事件监听器。方法:
$element.popover(popoverOpts)
.parent()
.delegate('button',
'click',
function(e) {
...
首先,您需要确保在指令被销毁时自行清理并取消绑定(bind)事件监听器(请查看文档中的life-cycle hooks)。下面是一个简单示例,说明了如何在指令 get 被销毁时解除绑定(bind)事件监听器:
// ...
// 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);
});
// ...
要解决您的问题,您需要确保注册事件监听器以满足您的需求。您可以阅读有关事件监听器的更多信息 here .
尽管说实话,看看你的代码,你应该给出 ui-bootstrap
尝试一下。
关于javascript - 确认按钮事件触发两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43286230/