簡體   English   中英

jQuery.on('click') 在 jQuery.click 之前?

[英]jQuery.on('click') before jQuery.click?

我有一個無法修改的外部腳本。 該腳本加載一個<a>按鈕,並在其上添加一個 jQuery .click...並以“return false”結束。

我需要在這次點擊中觸發我自己的代碼。 當我加載頁面時<a>不存在,所以我需要使用.on('click')來綁定“live”。 但看起來.on('click')是在.on('click')之后加載的,當他使用 "return false" 時,我的.on('click')沒有加載。

所以問題是......我怎樣才能觸發我點擊這個動態加載的a#btn,它已經有一個返回false的.click函數?

這是小提琴: http : //jsfiddle.net/PLpqU/

這里有一個代碼示例:

<div id="container"></div>
// I want this action to be executed on click, and the other too
// I can't use .click because on the "real" code, the a#btn is loaded after the page by another script
jQuery(document).on('click','a#btn',function(){
        ga('send', 'event', { eventCategory: 'xxxx', eventAction: 'yyyy' });
}) ;

// http://www.xxxxxx.com/distant-script.js
// This one is binded in a script that I cannot edit :
// Just before it load a#btn on the page, and then bind .click on it
// as he return false, the other on('click') are not executed
jQuery('#container').append('<a id="btn" />') ;
jQuery('a#btn').click(function(){
    // Some code stuff I need to be executed, but I can't manage
    return false ;
}) ;

如您所見,目標是在遠程腳本加載的鏈接按鈕上觸發 Google Analytics 事件。

您似乎面臨着多個問題,但更重要的是知道元素何時在 DOM 中呈現,以便您可以操作它的事件集合。

一旦元素可訪問,就很容易解除插件的處理程序綁定,綁定您的處理程序並重新綁定插件的處理程序,知道可以像這樣訪問 jQuery 的事件集合: $._data(domEl, 'events');

下面是一個例子:

var $div = $('<div>').click(function () { console.log('plugin'); return false; }),
    clickListener = jQuery._data($div[0], 'events').click[0];

//unbind all
$div.off('click');

//bind yours
$div.click(function () { console.log('yours'); });

//rebind the plugin's one
//note that I do not register the listener by honoring the same configs, 
//but you could since you can see them in the clickListener object
$div.click(clickListener.handler);

//test out everyting
$div.triggerHandler('click');

如果不想解綁,相信也可以使用DOM level 0事件模型,這樣做:

element.onclick = yourHandler;

知道,如果插件異步呈現該元素並且不提供知道該過程何時完成的方法,則知道該元素何時可用是一個更大的問題。

如果您想支持舊瀏覽器,除了覆蓋插件的代碼(假設相關方法是公開的)或使用setInterval輪詢 DOM 直到您要查找的元素成為 DOM 的一部分,您別無選擇,然后您就可以做我們上面討論的。

如果您的目標是現代瀏覽器,則可以使用MutationObserver對象來監聽 DOM 更改。

您可以取消綁定事件,然后將您的函數添加為事件處理程序。 http://api.jquery.com/unbind/

檢查這個 jsfiddle http://jsfiddle.net/Xm5MB/

$(function(){

    $("#testDiv").append("<a id='btn'>link</a>");
    $("a#btn").click(function(){
        alert("first bind");
    });
    $("a#btn").unbind("click");
    $("a#btn").on("click", function(){
        alert("second bind");
    });
});

可能有效的一件事是將您要首先觸發的點擊事件綁定到另一個點擊事件綁定到的元素的子元素。 由於 click 事件會從 DOM 的最低級別冒泡到最高級別,因此它應該在綁定到其父級的處理程序之前觸發綁定到子級的所有處理程序。

如果您想阻止其他事件觸發,您可以手動使用event.stopPropagation()或從您綁定到子項的函數返回false ,該函數調用event.stopPropagation()event.preventDefault()

這是@plalx 提供的解決方案:

var os = jQuery('#container') ; // the #container is written by me on the code. He's empty on load and is filled by the distant script wich add the a#btn on it.
if ( os.length > 0 ) // I just check if he is on my page, just in case.
{
    var timer = setInterval(function () 
    {
        var btn_os = jQuery('a#btn') ;
        if (btn_os.length) // Button is loaded on page : we can do the trick
        {
            clickListener = jQuery._data(btn_os[0], 'events').click[0]; // caching the first .click bind

            btn_os.off('click'); // Removing all binds

            // Adding my own bind
            btn_os.click(function () {
                console.log('test') ;
                ga('send', 'event', { eventCategory: 'xxxx', eventAction: 'yyyy', eventLabel : 'zzzz' });
                // You can either trigger here the previous handler or rebind it out of here, 6 lines bottom
                // In my case i prefer to trigger it myself, with a little delay to make sure that my ga('send') has time to register
                setTimeout(function(){clickListener.handler() ;}, 150);
            });

            // And rebinding the old one if needed
            // In my particular case i don't want to rebind it, i prefer triggering it manually on my .click function with a setTimeout delay
            // btn_os.click(clickListener.handler);
            clearInterval(timer) ; // Removing the interval timer
        }
    }
    , 100);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM