【问题标题】:How can I programmatically invoke an onclick() event from a anchor tag while keeping the ‘this’ reference in the onclick function?如何以编程方式从锚标记调用 onclick() 事件,同时在 onclick 函数中保留“this”引用?
【发布时间】:2010-10-28 17:38:06
【问题描述】:

以下不起作用...(至少在 Firefox 中不起作用:document.getElementById('linkid').click() 不是函数)

<script type="text/javascript">
    function doOnClick() {
        document.getElementById('linkid').click();
        //Should alert('/testlocation');
    }
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>

【问题讨论】:

    标签: javascript dom-events


    【解决方案1】:

    您需要在该元素的上下文中apply 事件处理程序:

    var elem = document.getElementById("linkid");
    if (typeof elem.onclick == "function") {
        elem.onclick.apply(elem);
    }
    

    否则this 将引用执行上述代码的上下文。

    【讨论】:

    • 我认为你是唯一一个不认为我是傻瓜的人(因为没有提到括号表示法/onclick|click 浏览器不兼容)。准点!
    • 考虑一下:howtocreate.co.uk/tutorials/javascript/domevents -- 调用 onclick 函数会调用 所有 注册的事件处理程序吗?此外,错误调用事件不会产生与该事件关联的默认操作(例如表单提交)。
    • Gumbo,因为这段代码确实产生了不同的结果,它仍然不能与 Microsoft.Ajax 和 Microsoft.AjaxMvc 库一起使用......
    • 为什么在这里使用apply()?你可以只做elem.onclick();elem 将是函数中的“this”引用——很简单!
    【解决方案2】:

    解决此问题的最佳方法是使用 Vanilla JS,但如果您已经在使用 jQuery,则有一个非常简单的解决方案:

    <script type="text/javascript">
        function doOnClick() {
            $('#linkid').click();
        }
    </script>
    <a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
    

    在 IE8-10、Chrome、Firefox 中测试。

    【讨论】:

    • 为什么投反对票?请评论一个原因,如果您认为有问题,我可以改进我的问题。
    • 如果 OP 没有在问题上明确提到它,你不应该提供依赖于外部资源(如 jQuery 之类的库)的答案,我认为它是促使人们投票的原因
    • 早在 2013 年,每个人都在使用 jquery - 但现在,我同意 :) - 我会保留答案以供将来参考。
    【解决方案3】:

    要触发事件,您基本上只需为此调用事件处理程序 元素。对您的代码稍作改动。

    var a = document.getElementById("element");
    var evnt = a["onclick"];
    
    if (typeof(evnt) == "function") {
        evnt.call(a);
    }
    

    【讨论】:

    • +1。此外,谷歌搜索显示 foo.click() 只是 IE,当然我可能是错的......
    • 您应该使用点表示法 (.onclick) 而不是括号表示法 (["onclick"])。
    • .onclick() 或 .click() 都不能按预期工作。在 Firefox 中 .click (或带括号的 ['click'])它是“不是一个功能”。但是在调用 .onclick() 时,您会丢失“this”引用(我在 ASP.NET MVC 中需要它,因为执行函数中需要来自 标记的信息)
    【解决方案4】:

    当然,OP 非常相似地表示这不起作用,但它对我有用。根据我的源代码中的注释,它似乎是在 OP 的帖子前后或之后实施的。也许现在更标准了。

    document.getElementsByName('MyElementsName')[0].click();
    

    就我而言,我的按钮没有 ID。如果您的元素有 id,最好使用以下(未经测试)。

    document.getElementById('MyElementsId').click();
    

    我最初尝试过这种方法,但没有奏效。谷歌搜索后,我回来发现我的元素是按名称命名的,并且没有 ID。仔细检查您是否调用了正确的属性。

    来源:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click

    【解决方案5】:
    $("#linkid").trigger("click");
    

    【讨论】:

    • 欢迎来到 SO。您能否详细说明为什么会这样(它究竟做了什么等)以及它与其他解决方案的不同之处?
    • 为什么要标记这个答案?如果您使用 jquery,这是此页面上的最佳解决方案...一个班轮 - 无法击败!
    • 答案应该不需要jQuery
    【解决方案6】:

    旧线程,但问题仍然相关,所以...

    (1) 您问题中的示例现在 DOES 在 Firefox 中工作。然而,除了调用事件处理程序(显示警报)之外,它点击链接,导致导航(一旦警报被解除)。

    (2)只需调用事件处理程序(不触发导航)只需替换:

    document.getElementById('linkid').click();
    

    document.getElementById('linkid').onclick();
    

    【讨论】:

      【解决方案7】:

      看看handleEvent方法
      https://developer.mozilla.org/en-US/docs/Web/API/EventListener

      “原始”Javascript:

      function MyObj() {
         this.abc = "ABC";
      }
      MyObj.prototype.handleEvent = function(e) {
         console.log("caught event: "+e.type);
         console.log(this.abc);
      }
      
      var myObj = new MyObj();
      
      document.querySelector("#myElement").addEventListener('click', myObj);
      

      现在单击您的元素(id 为“myElement”),它应该在控制台中打印以下内容:

      捕获事件:点击
      ABC

      这允许您拥有一个对象方法作为事件处理程序,并可以访问该方法中的所有对象属性。

      不能直接将对象的方法传递给 addEventListener(例如:element.addEventListener('click',myObj.myMethod);)并期望 myMethod 像正常调用该对象一样行事。我猜测传递给 addEventListener 的任何函数都会以某种方式被复制而不是被引用。例如,如果您将事件侦听器函数引用传递给 addEventListener(以变量的形式)然后取消设置此引用,则事件侦听器在捕获事件时仍会执行。

      另一种(不太优雅)的解决方法是将方法作为事件侦听器传递并仍然是this,并且仍然可以访问事件侦听器中的对象属性,如下所示:

      // see above for definition of MyObj
      
      var myObj = new MyObj();
      
      document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));
      

      【讨论】:

        【解决方案8】:

        如果您纯粹使用它来引用 onclick 属性中的函数,这似乎是一个非常糟糕的主意。一般来说,内联事件是个坏主意。

        我建议如下:

        function addEvent(elm, evType, fn, useCapture) {
            if (elm.addEventListener) {
                elm.addEventListener(evType, fn, useCapture);
                return true;
            }
            else if (elm.attachEvent) {
                var r = elm.attachEvent('on' + evType, fn);
                return r;
            }
            else {
                elm['on' + evType] = fn;
            }
        }
        
        handler = function(){
           showHref(el);
        }
        
        showHref = function(el) {
           alert(el.href);
        }
        
        var el = document.getElementById('linkid');
        
        addEvent(el, 'click', handler);
        

        如果你想从其他javascript代码中调用相同的函数,模拟点击调用函数并不是最好的方法。考虑:

        function doOnClick() {
           showHref(document.getElementById('linkid'));
        }
        

        【讨论】:

        • 这是关于保留对“this”的引用。我不能单独在锚点(.NET MVC)中生成 onclick 部分。我需要生成一个完整的锚标签。 onclick 函数完全需要此标记(例如,它使用 href 属性)。
        【解决方案9】:

        一般来说,我建议不要“手动”调用事件处理程序。

        • 由于多次注册,不清楚执行了什么 听众
        • 有进入递归和无限事件循环的危险(单击 A 触发点击B,触发点击A等)
        • 对 DOM 的冗余更新
        • 很难将由用户引起的视图中的实际更改与作为初始化代码(应该只运行一次)所做的更改区分开来。

        最好弄清楚你到底想要发生什么,把它放在一个函数中并手动调用它并将它注册为事件监听器。

        【讨论】:

        • OP 询问如何做某事,而不是什么是做某事的最佳方式。这不是 CodeReview。如果你回答了他的问题,然后发表了免责声明,那就不一样了。
        猜你喜欢
        • 2013-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多