如何在单击<a>链接时显示确认对话框?

346

我希望这个链接有一个 JavaScript 对话框,询问用户“您确定吗?Y/N”。

<a href="delete.php?id=22">Link</a>
如果用户点击“Yes”,则链接应该加载,如果点击“No”,则不会发生任何事情。
我知道如何在表单中做到这一点,使用onclick运行返回truefalse的函数。但是如何在<a>链接中实现这一点?
10个回答

753

内联事件处理程序

最简单的方式是可以在内联onclick处理程序中使用confirm()函数。

<a href="delete.php?id=22" onclick="return confirm('Are you sure?')">Link</a>

高级事件处理

但通常情况下,您希望分离HTML和Javascript,因此建议您不要使用内联事件处理程序,而是在链接上添加一个类,并为其添加事件监听器。

<a href="delete.php?id=22" class="confirmation">Link</a>
...
<script type="text/javascript">
    var elems = document.getElementsByClassName('confirmation');
    var confirmIt = function (e) {
        if (!confirm('Are you sure?')) e.preventDefault();
    };
    for (var i = 0, l = elems.length; i < l; i++) {
        elems[i].addEventListener('click', confirmIt, false);
    }
</script>

这个例子只能在现代浏览器中使用(对于旧版本的IE,你可以使用attachEvent(), returnValue并提供getElementsByClassName()的实现或者使用像jQuery这样的库来解决跨浏览器问题)。你可以在MDN上了解更多有关此高级事件处理方法的信息

jQuery

我不想被认为是jQuery的铁杆粉丝,但DOM操作和事件处理正是它在处理浏览器差异时最有用的两个领域。只是为了好玩,下面是使用jQuery的代码:

<a href="delete.php?id=22" class="confirmation">Link</a>
...
<!-- Include jQuery - see http://jquery.com -->
<script type="text/javascript">
    $('.confirmation').on('click', function () {
        return confirm('Are you sure?');
    });
</script>

1
@Tophe 确认对话框本身与特定元素无关。 - kapa
1
对于这么简单的东西,真的有必要将HTML和JavaScript分开吗?如果将如此简单且短小的函数内联,您预见到会出现什么问题? - Ciaran Gallagher
5
@CiaranG 开始总是这样:),然后你会添加这个和那个等等。如果您能够遵循关注点分离原则,那么如果您摆脱大部分的内联处理程序,您会感觉更加清爽。它们只是与HTML无关。至少在我看来,在大多数情况下都是如此。总是有特殊情况-懒惰不应该是其中之一。 - kapa
根据您的编辑建议,在内联处理程序中省略confirm(...)后面的分号时存在一个错误。我无法重现那个错误。 - Sebastian Simon
将JavaScript和HTML分离并不总是可取的。在您<s>高级</s>误导性事件处理中,无法从HTML中判断链接是否被跟踪(因为JS已分离)。这也可能会混淆机器人,它们通常仅解析HTML本身,而不需要额外的HTTP请求。此外,即使是10年后,jQuery注释也已经过时。 - Jan Turoň
显示剩余2条评论

38

您也可以尝试这样做:

<a href="" onclick="if (confirm('Delete selected item?')){return true;}else{event.stopPropagation(); event.preventDefault();};" title="Link Title">
    Link Text
</a>

@kapa 给出的答案非常简单,而且不那么混乱。 - dipenparmar12
干得好。我想调用另一个在确认成功时调用的JS方法。这将解决我的问题。 - Ehsan ul haq
1
将return false、preventDefault()、stopPropagation()以及其他任何与抑制相关的方法混合在一起是非常丑陋的想法。在链接中,点击事件的传播没有任何意义。如果不想依赖return false(因为有些人报告说它有时不起作用),则onclick="confirm('really?') || event.preventDefault()"可以做到与您的代码相同的效果,而不会产生无关的混乱。 - Jan Turoň
可以简化为 onclick="return confirm('删除选定的项目?');" - Latheesan

19

我建议避免使用内联JavaScript:

var aElems = document.getElementsByTagName('a');

for (var i = 0, len = aElems.length; i < len; i++) {
    aElems[i].onclick = function() {
        var check = confirm("Are you sure you want to leave?");
        if (check == true) {
            return true;
        }
        else {
            return false;
        }
    };
}​

JS Fiddle演示。上述内容已更新以减少空间,但保持清晰度/功能。

var aElems = document.getElementsByTagName('a');

for (var i = 0, len = aElems.length; i < len; i++) {
    aElems[i].onclick = function() {
        return confirm("Are you sure you want to leave?");
    };
}

JS Fiddle演示

稍有延迟的更新,使用addEventListener()(如下方评论中bažmegakapa所建议):

function reallySure (event) {
    var message = 'Are you sure about that?';
    action = confirm(message) ? true : event.preventDefault();
}
var aElems = document.getElementsByTagName('a');

for (var i = 0, len = aElems.length; i < len; i++) {
    aElems[i].addEventListener('click', reallySure);
}

JS Fiddle演示

上述代码将一个函数绑定到每个单独链接的事件,这可能会非常浪费资源。相反地,您可以将事件处理(使用委托)绑定到祖先元素,例如以下代码:

function reallySure (event) {
    var message = 'Are you sure about that?';
    action = confirm(message) ? true : event.preventDefault();
}

function actionToFunction (event) {
    switch (event.target.tagName.toLowerCase()) {
        case 'a' :
            reallySure(event);
            break;
        default:
            break;
    }
}

document.body.addEventListener('click', actionToFunction);

JS Fiddle演示

由于事件处理程序附加到body元素,该元素通常包含许多其他可点击的元素,因此我使用了一个中间函数(actionToFunction)来确定如何处理该点击事件。如果被点击的元素是链接,因此具有tagNamea,则将点击处理传递给reallySure()函数。

参考资料:


谢谢。短的内联确认解决方案起作用了。为什么建议避免内联代码?我通常会避免使用内联CSS,原因显而易见,但在简短的JavaScript片段中有什么原因呢? - Christoffer
出于完全相同的原因,内联CSS是不可取的,它更难以维护,会导致HTML混乱,并且如果需求发生变化,需要付出过多的工作量来更新。 - David Thomas
我同意不使用内联处理程序的观点。但是,如果我们无论如何在脚本中附加处理程序,应该使用先进模型(addEventListener). 虽然+1。 - kapa
@bažmegakapa:我倾向于同意;但我必须承认,我还没有完全适应addEventListener()模型。 - David Thomas
你可以用 if(check) 替换 if(check == true) - Anonymous
请只返回 return confirm("确定要离开吗?"); 并节省6行。 - Florian F

17
<a href="delete.php?id=22" onclick = "if (! confirm('Continue?')) { return false; }">Confirm OK, then goto URL (uses onclick())</a>

1

jAplus

您可以在不编写JavaScript代码的情况下完成它。

<head>
   <script src="/path/to/jquery.js" type="text/javascript" charset="utf-8"></script>
   <script src="/path/to/jquery.Aplus.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
...
   <a href="delete.php?id=22" class="confirm" title="Are you sure?">Link</a>
...
</body>

演示页面


12
谢谢分享,不过当然你在使用Javascript,你添加了一个整个库来处理一些非常简单的事情。这值得吗?我不知道那个库,我将阅读一下,如果你也用它处理其他事情,或许额外的负荷是值得的... - Marcos Buarque
1
这么简单的事情需要两个库吗? - maracuja-juice

1

使用PHP、HTML和JavaScript进行提示

如果有人想要在单个文件中使用php、html和javascript,下面的答案对我有效。我使用了Bootstrap图标“trash”作为链接。

<a class="btn btn-danger" href="<?php echo "delete.php?&var=$var"; ?>" onclick="return confirm('Are you sure want to delete this?');"><span class="glyphicon glyphicon-trash"></span></a>

我在中间使用PHP代码的原因是因为我不能从一开始就使用它。

下面的代码对我不起作用:

echo "<a class='btn btn-danger' href='delete.php?&var=$var' onclick='return confirm('Are you sure want to delete this?');'><span class='glyphicon glyphicon-trash'></span></a>";

我对它进行了修改,就像第一个代码一样,然后按照我所需的方式运行。我希望能够帮助需要我的情况下的某个人。


1

内联代码:

<a href="delete.php?id=22" onclick="if(!confirm('Are you sure to Delete This?')){ event.preventDefault() }">Link</a>

如果你从不想添加内联JS,那么可以使用这种方式。
外部代码:
html
<a href="delete.php?id=22" onclick="sureToDelete(event)">Link</a>

Javascript

    function sureToDelete(e){
        if(confirm('Are You sure you want to delete this?')){
            return true;
        }else{
            e.preventDefault();
        }
    }

0

如果你使用addEventListener(或attachEvent)来附加事件处理程序,那么这种方法与以上两种答案略有不同。

function myClickHandler(evt) {
  var allowLink = confirm('Continue with link?');
  if (!allowLink) {
    evt.returnValue = false; //for older Internet Explorer
    if (evt.preventDefault) {
      evt.preventDefault();
    }
    return false;
  }
}

你可以将此处理程序附加到以下任一:

document.getElementById('mylinkid').addEventListener('click', myClickHandler, false);

或者对于旧版本的Internet Explorer:

document.getElementById('mylinkid').attachEvent('onclick', myClickHandler);

如果你关心旧版IE,请不要忘记window.event - kapa

0

只是为了好玩,我将使用整个文档上的单个事件,而不是添加事件到所有锚标签:

document.body.onclick = function( e ) {
    // Cross-browser handling
    var evt = e || window.event,
        target = evt.target || evt.srcElement;

    // If the element clicked is an anchor
    if ( target.nodeName === 'A' ) {

        // Add the confirm box
        return confirm( 'Are you sure?' );
    }
};

如果你有很多锚点标签,这种方法会更有效率。当然,如果你将此事件添加到包含所有锚点标签的容器中,它会变得更加高效。


0

大多数浏览器不会显示传递给confirm()的自定义消息。

使用此方法,如果用户更改了任何<input>字段的值,您可以显示带有自定义消息的弹出窗口。

您可以将此仅应用于某些链接,甚至是页面中的其他HTML元素。只需为所有需要确认的链接添加自定义类,并使用以下代码:

$(document).ready(function() {
  let unsaved = false;
  // detect changes in all input fields and set the 'unsaved' flag
  $(":input").change(() => unsaved = true);
  // trigger popup on click
  $('.dangerous-link').click(function() {
    if (unsaved && !window.confirm("Are you sure you want to nuke the world?")) {
      return; // user didn't confirm
    }
    // either there are no unsaved changes or the user confirmed
    window.location.href = $(this).data('destination');
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<input type="text" placeholder="Nuclear code here" />
<a data-destination="https://en.wikipedia.org/wiki/Boom" class="dangerous-link">
    Launch nuke!
</a>

尝试更改示例中的输入值,以预览其工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接