如果我尚未通过bind或click绑定事件处理程序,是否可以调用jquery click()跟随<a>链接?


175

我的JavaScript中有一个计时器,该计时器需要模拟时间流逝后单击链接以转到另一个页面。为此,我使用了jQuery的click()功能。我已经用过了$().trigger()window.location也可以使用,并且我可以使这三个都按预期工作。

我观察到一些奇怪的行为,click()并且试图了解会发生什么以及为什么。

我在这个问题中描述的所有内容都使用了Firefox,但我也对其他浏览器将如何使用它感兴趣。

如果我没有使用过$('a').bind('click',fn)或未$('a').click(fn)设置事件处理程序,则调用$('a').click()似乎根本不起作用。它不会为此事件调用浏览器的默认处理程序,因为浏览器不会加载新页面。

但是,如果我先设置一个事件处理程序,那么即使该事件处理程序不执行任何操作,它也可以按预期工作。

$('a').click(function(){return true;}).click();

这将加载新页面,就像我自己单击a一样。

所以我的问题是双重的:这是怪异的行为,因为我在某处做错了什么吗?click()如果我还没有创建自己的处理程序,为什么调用对默认行为不起作用?

编辑:

正如霍夫曼确定何时尝试复制我的结果时,上述我所说的结果实际上并没有发生。我不确定是什么导致了昨天观察到的事件,但是今天我可以肯定,这不是我在问题中所描述的。

因此,答案是您不能在浏览器中“伪造”单击,而jQuery所做的只是调用事件处理程序。您仍然可以使用window.location更改页面,对我来说效果很好。


2
可能是一个解决办法: stackoverflow.com/questions/31687759/...
Sukrit尔斯基

Answers:


90

有趣的是,这可能是jQuery的“功能请求”(即错误)。如果将jQuery事件绑定到元素,则jQuery click事件仅触发元素上的click操作(在DOM上称为onClick事件)。您应该转到jQuery邮件列表(http://forum.jquery.com/)并进行报告。这可能是通缉犯,但我不这么认为。

编辑:

我做了一些测试,您说的是错误的,即使您将函数绑定到'a'标记,它仍然无法将您带到href属性指定的网站。尝试以下代码:

<html>
<head>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
 <script>
  $(document).ready(function() {
   /* Try to dis-comment this:
   $('#a').click(function () {
    alert('jQuery.click()');
    return true;
   });
   */
  });
  function button_onClick() {
   $('#a').click();
  }
  function a_onClick() {
   alert('a_onClick');
  }
 </script>

</head>
<body>
 <input type="button" onclick="button_onClick()">
 <br>
 <a id='a' href='http://www.google.com' onClick="a_onClick()"> aaa </a>

</body>
</html> 

除非您直接单击链接(带有或不带有注释代码),否则它永远不会进入google.com。还要注意,即使将click事件绑定到链接,单击按钮也不会变成紫色。如果直接单击链接,它会变成紫色。

我进行了一些研究,似乎.click不能与'a'标记一起使用,因为浏览器不会支持javascript的“假点击”。我的意思是,您无法使用javascript“单击”元素。使用'a'标签,您可以触发其onClick事件,但是链接不会更改颜色(对于已访问的链接颜色,在大多数浏览器中默认为紫色)。因此,使$()。click事件与'a'标签一起使用是没有意义的,因为转到href属性的动作不是onClick事件的一部分,而是在浏览器中进行了硬编码。


7
我尝试了您的代码,它的功能与您所说的完全相同,但是我的代码却如上所述。我将做更多的实验,看看是否可以将您可以尝试的结果的简单示例放在一起。
Mnebuerquo

1
好。一定是我做错了。我在发布问题时绝对确定它是有效的,但是由于我尝试了您的示例,因此我的问题不再有效。我将仅返回使用window.location更改页面,而不尝试伪造点击。
Mnebuerquo

实际上,click()并不是要创建虚假点击,但是有时我们可以使用它来单击带有javascript注入的按钮或表单,或者只是为了方便,同时在现有javascript函数之上创建临时热键。
王王航空

241

当然,另一种选择是只使用香草javascript:

document.getElementById("a_link").click()

1
这在Safari中不起作用,根据HTML规范,只有输入才需要实现。
杰里米·考夫曼

4
ang!确实有效!但我必须说,这是不是很“香草”的JavaScript,因为它是一个使用jQuery的元素,所以它的排序的香草的jQuery JavaScript的....这在Firefox 24和IE 10
bgmCoder

@BGM,好的,但是click()不在jquery元素上。您可以将其替换为getElementById(“ ..”)。click()
彼得

伤口很饱,按我的预期工作。+1 :)。对于其他用户,您也可以使用:var lnk = document.getElementById(“ a_link”); if(lnk == null){//做点...。} else {lnk.click(); }
Iqbal 2014年

IE10和Jquery 1.6.4在各种浏览器中进行了测试,无法处理此问题。
汉尼斯·施耐德

65

如果您看一下$.click我敢打赌的函数代码,则有一条条件语句,该语句检查在click事件发生之前该元素是否已为事件注册了侦听器。为什么不href从链接中获取属性并手动更改页面位置呢?

 window.location.href = $('a').attr('href');

编辑:这就是为什么它不会从trigger功能中单击版本1.3.2的jQuery源的原因:

 // Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
    if ( (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
        event.result = false;

    // Trigger the native events (except for clicks on links)
    if ( !bubbling && elem[type] && !event.isDefaultPrevented() && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
        this.triggered = true;
        try {
            elem[ type ]();
        // prevent IE from throwing an error for some hidden elements
        } catch (e) {}
    }

调用处理程序(如果有)之后,jQuery会在对象上触发一个事件。但是,如果元素不是链接,则仅为单击事件调用本机处理程序。我猜这是出于某种原因而有目的地完成的。尽管是否定义了事件处理程序,这都应该是正确的,因此我不确定为什么在您的情况下附加事件处理程序会导致onClick调用本机处理程序。您必须做我所做的事情,并逐步执行该执行程序,以查看它在哪里被调用。


我当然可以使用我在问题中提到的window.location和href。我试图了解jquery click()中会发生什么,以及导致我观察到的结果的原因。
Mnebuerquo

我编辑了答案,以显示它在jQuery源代码中处理$ .click()链接调用的位置。
瑞安·林奇

2
window.location可以运行,但不能发布HTTP Referrer,并中断后退按钮。
Chase Seibert

5

锚标记上的单击处理程序是jQuery中的一种特殊情况。

我认为您可能会在锚点的onclick事件(浏览器知道)与jQuery对象的click事件之间感到困惑,该jQuery对象包装了锚点标记的DOM概念。

您可以在此处下载jQuery 1.3.2源。

源代码的相关部分是第2643-2645行(我将其分成多行以使其更容易理解):

// Handle triggering native .onfoo handlers (and on links since we don't call .click() for links)
if (
     (!elem[type] || (jQuery.nodeName(elem, 'a') && type == "click")) && 
       elem["on"+type] && 
       elem["on"+type].apply( elem, data ) === false
   )
     event.result = false;

5

JS / jQuery不支持以编程方式“单击”链接的默认行为。

您可以做的就是创建一个表单并提交。这样,您就不必使用window.location或了window.open,它们通常被浏览器阻止为不需要的弹出窗口。

该脚本有2种不同的方法:一种尝试打开3个新标签页/窗口(它仅在IE和Chrome中打开1个,以下提供更多信息),另一种在链接点击时触发自定义事件。

方法如下:

的HTML

<html>
<head>
    <script src="jquery-1.9.1.min.js" type="text/javascript"></script>
    <script src="script.js" type="text/javascript"></script>
</head>
<body>
    <button id="testbtn">Test</button><br><br>

    <a href="https://google.nl">GOOGLE</a><br>
    <a href="http://en.wikipedia.org/wiki/Main_Page">WIKI</a><br>
    <a href="https://stackoverflow.com/">SO</a>
</body>
</html>

jQuery(script.js)

$(function()
{ 
    // Try to open all 3 links by pressing the button
    // - Firefox opens all 3 links
    // - Chrome only opens 1 of them without popup warning
    // - IE only opens 1 of them WITH popup warning
    $("#testbtn").on("click", function()
    {
        $("a").each(function()
        {
            var form = $("<form></form>");
            form.attr(
            {
                id     : "formform",
                action : $(this).attr("href"),
                method : "GET",
                // Open in new window/tab
                target : "_blank"
            });

            $("body").append(form);
            $("#formform").submit();
            $("#formform").remove();
        });
    });

    // Or click the link and fire a custom event 
    // (open your own window without following the link itself)
    $("a").on("click", function()
    {
        var form = $("<form></form>");
        form.attr(
        {
            id     : "formform",
            // The location given in the link itself
            action : $(this).attr("href"), 
            method : "GET",
            // Open in new window/tab
            target : "_blank"              
        });

        $("body").append(form);
        $("#formform").submit();
        $("#formform").remove();

        // Prevent the link from opening normally
        return false;
    });

});

它对每个链接元素的作用是:

  1. 建立表格
  2. 给它属性
  3. 将其附加到DOM,以便可以提交
  4. 提交
  5. 从DOM中删除表单,删除所有痕迹*插入邪恶的笑声*

现在,您有一个新的选项卡/窗口加载"https://google.nl"(或您想要的任何URL,只需替换它)。不幸的是,当您尝试以这种方式打开多个窗口Popup blocked时,尝试打开第二个窗口时仍会收到一个消息栏(第一个窗口仍处于打开状态)。


有关如何使用此方法的更多信息,请参见:

不使用window.open或打开新窗口/标签window.location.href


3

触发您要连接jquery .click()的元素内的Hyperlink元素。

<div class="TopicControl">
    <div class="articleImage">
       <a href=""><img src="" alt=""></a>
    </div>
</div>

在脚本中,您连接到要单击事件的主容器。然后,您使用标准的jquery方法来查找元素(类型,类,id)并触发点击。发生的情况是,jquery进入一个递归函数以触发单击,然后您通过采取事件'e'和stopPropagation()函数来中断递归函数,并返回false,因为您不希望jquery除了触发链接之外还做其他任何事情。

$('.TopicControl').click(function (event) {
         $(this).find('a').click();
        event.stopPropagation();
        return false;
     });

另一种解决方案是将容器包装在元素中,然后将容器放置在容器中,而不是容器中。将跨度设置为显示块,以符合w3c标准。


3

您可以使用jQuery选择该元素的jQuery对象。然后,获取基础的DOM元素并调用其click()方法。

按编号

$("#my-link").each(function (index) { $(this).get(0).click() });

或使用jQuery按CSS类单击一堆链接

$(".my-link-class").each(function (index) { $(this).get(0).click() });

2

它没有任何作用,因为没有事件绑定到该事件。如果我没记错的话,jQuery会维护自己的事件处理程序列表,这些事件处理程序绑定到NodeLists是为了提高性能和其他目的。


2

如果您只需要一个案例或很少的案例,就需要使用此功能。(您的整个应用程序都不需要此功能)我宁愿保留jQuery(出于多种原因,包括能够更新到较新的版本,CDN等),并具有以下解决方法:

// For modren Browsers
$(ele).trigger("click");

// Relaying on Paul Irish's conditional class names http://bit.ly/HWIpAp (via HTML5 Boilerplate http://bit.ly/HUzi3I) where each IE version gets a class of its Version
$("html.ie7").length && (function(){
    var eleOnClickattr = $(ele).attr("onclick") 
    eval(eleOnClickattr);
  })()

1

要在同一选项卡中打开超链接,请使用:

$(document).on('click', "a.classname", function() {
    var form = $("<form></form>");
    form.attr(
    {
        id     : "formid",
        action : $(this).attr("href"),
        method : "GET",
    });

    $("body").append(form);
    $("#formid").submit();
    $("#formid").remove();
    return false;
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.