Javascript 动态创建元素上的事件绑定?

Javascript 动态创建元素上的事件绑定?,javascript,jquery,events,unobtrusive-javascript,Javascript,Jquery,Events,Unobtrusive Javascript,我有一段代码,我在页面上的所有选择框中循环,并将一个.hover事件绑定到它们,以便在打开/关闭鼠标时对它们的宽度进行一些微调 这发生在PageReady上,效果很好 我的问题是,在初始循环之后通过Ajax或DOM添加的任何选择框都不会绑定事件 我已经找到了这个插件,但是在我用插件向我的页面添加另一个5k之前,我想看看是否有人知道这样做的方法,无论是直接使用jQuery还是通过其他选项。您可以在创建对象时向对象添加事件。如果要在不同的时间向多个对象添加相同的事件,则创建命名函数可能是一种方法 v

我有一段代码,我在页面上的所有选择框中循环,并将一个.hover事件绑定到它们,以便在打开/关闭鼠标时对它们的宽度进行一些微调

这发生在PageReady上,效果很好

我的问题是,在初始循环之后通过Ajax或DOM添加的任何选择框都不会绑定事件


我已经找到了这个插件,但是在我用插件向我的页面添加另一个5k之前,我想看看是否有人知道这样做的方法,无论是直接使用jQuery还是通过其他选项。

您可以在创建对象时向对象添加事件。如果要在不同的时间向多个对象添加相同的事件,则创建命名函数可能是一种方法

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() {
    // On the document load, apply to existing elements
    $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;

您可以简单地将事件绑定调用包装到一个函数中,然后调用它两次:一次在文档就绪时调用,一次在添加新DOM元素的事件之后调用。如果这样做,您将希望避免在现有元素上绑定同一事件两次,因此您需要解除现有事件的绑定,或者最好只绑定到新创建的DOM元素。代码如下所示:

function addCallbacks(eles){
    eles.hover(function(){alert("gotcha!")});
}

$(document).ready(function(){
    addCallbacks($(".myEles"))
});

// ... add elements ...
addCallbacks($(".myNewElements"))
从jQuery 1.7开始,您应该在填充选择器参数的情况下使用:

$(staticAncestors).on(eventName, dynamicChild, function() {});
说明:

这称为事件委派,其工作原理如下。事件附加到应处理的元素的静态父元素。每次事件在此元素或一个子元素上触发时,都会触发此jQuery处理程序。然后,处理程序检查触发事件的元素是否与选择器dynamicChild匹配。当存在匹配项时,将执行自定义处理程序函数

在此之前,推荐的方法是使用:

然而,live在1.7中被弃用,取而代之的是on,并在1.9中被完全删除。现场签名:

$(selector).live( eventName, function(){} );
$(document).on( eventName, selector, function(){} );
。。。可替换为以下签名:

$(selector).live( eventName, function(){} );
$(document).on( eventName, selector, function(){} );
例如,如果您的页面正在动态创建类名为dosomething的元素,您会将事件绑定到已存在的父级,这是问题的关键所在,您需要绑定到已存在的内容,而不是绑定到动态内容,这可以是,最简单的选项是document。尽管要记住

绑定事件时存在的任何父级都可以。比如说

$('.buttons').on('click', 'button', function(){
    // do something here
});
适用于

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>

试着使用。活着而不是。束缚;在Ajax请求执行后,.live将绑定.hover到您的复选框。

您可以使用live方法将元素(甚至是新创建的元素)绑定到事件和处理程序,如onclick事件

下面是我编写的示例代码,您可以看到live方法如何将所选元素(甚至是新创建的元素)绑定到事件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function()
                {
                    $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function()
                    {
                        $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){
                        //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button);
                    });
                    /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>

在的文档中有一个很好的解释

简言之:

事件处理程序仅绑定到当前选定的元素;在代码调用.on时,它们必须存在于页面上

因此,在下面的示例中,在生成代码之前,必须存在数据表tbody tr

$("#dataTable tbody tr").on("click", function(event){
    console.log($(this).text());
});
如果将新的HTML注入页面,则最好使用委派事件来附加事件处理程序,如下所述

委派事件的优点是,它们可以处理来自子元素的事件,这些子元素将在以后添加到文档中。例如,如果表存在,但行是使用代码动态添加的,则以下操作将对其进行处理:

$("#dataTable tbody").on("click", "tr", function(event){
    console.log($(this).text());
});
除了能够处理尚未创建的子元素上的事件外,委托事件的另一个优点是,当必须监视许多元素时,它们的开销可能会低得多。在tbody中有1000行的数据表上,第一个代码示例将处理程序附加到1000个元素

委托事件方法第二个代码示例只将事件处理程序附加到一个元素tbody,事件只需要从单击的tr冒泡到tbody一个级别

注意:委派事件不适用于。

这是一个没有任何库或插件的纯JavaScript解决方案:

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);
哈斯班在哪里

这归功于戴夫和西姆·维达斯

使用更现代的JS,hasClass可以实现为:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}

另一个解决方案是在创建元素时添加侦听器。在创建元素时,您将侦听器放入元素中,而不是将其放入主体中:

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}

我更喜欢使用选择器,并将其应用于文档

这将在文档上绑定自身,并将适用于页面加载后呈现的元素

例如:

$(document).on("click", 'selector', function() {
    // Your code here
});
绑定事件时存在的任何父级,如果您的页面正在使用“类名”按钮动态创建元素,则会将事件绑定到已存在的父级

$document.readyfunction{ //特定家长点击 $.buttons.onclick,按钮,函数{ 警报点击; }; //按钮类上的动态事件绑定 $document.onclick、.按钮、函数{ alertDymamic点击; }; $input.addClassbutton; }; 2. 3. 6动态创建元素上的事件绑定 单一元素:

子元素:

请注意添加的*。将为该元素的所有子元素触发一个事件

我注意到:

$(document.body).on('click','.#element_id > element', function(e) {  });

它不再起作用了,但它以前起过作用。我一直在使用谷歌的jQuery,但我不知道他们是否改变了它。

注意元素所在的主类,例如

<div class="container">
     <ul class="select">
         <li> First</li>
         <li>Second</li>
    </ul>
</div>
试着这样做-

$(document).on( 'click', '.click-activity', function () { ... });
你可以用

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

这两种方法是等效的,但参数顺序不同

请参阅:

使用jQuery的.on方法将事件处理程序附加到活动元素


同样从版本1.9开始。live方法被删除。

当使用动态创建时,您可以将事件附加到元素

从jQuery 1.8开始,任何jQuery实例方法(jQuery.fn的方法)都可以用作传递给 第二个参数:

函数handleDynamicElementEventevent{ console.logevent.type,this.value } //创建事件并将其附加到动态元素 jQuery{ html:$.maparay3,函数,索引{ 返回新选项索引,索引 }, 关于:{ 更改:handleDynamicElementEvent } } .附体;
另一个创建元素和绑定事件的灵活解决方案


注意:这将为每个元素创建一个事件处理程序实例,在循环中使用时可能会影响性能。以下是动态创建的元素不响应单击的原因:

var body=$body; var btns=$按钮; var btnB=$B; //文件中还没有“B”。 //因此,“$button”给出了“[A]”。 //只有'A'获得单击侦听器。 btns.onclick,函数{ console.logthis; }; //对'B'来说太晚了。。。 body.appendbtnB;
A我正在寻找一种解决方案,使$.bind和$.unbind在动态添加的元素中能够正常工作

As采用了附加事件的技巧,以便在我访问的对象上创建一个假解绑:

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );

将事件绑定到已存在的父级:

$(document).on("click", "selector", function() {
    // Your code here
});

我更喜欢以模块化功能方式部署事件侦听器,而不是编写文档级事件侦听器的脚本。所以,我确实喜欢下面。注意,不能使用同一个事件侦听器过度订阅元素,因此不必担心多次附加侦听器,只需附加一个

var迭代次数=4次; var按钮; var body=document.querySelectorbody; 对于var i=0;i<迭代次数;i++{ 按钮=document.createElementbutton; button.classList.addmy-button; button.appendChilddocument.createTextNodei; button.addEventListenerclick,MyButton已单击; body.appendChildbutton; } 函数myButtonWasClickede{ console.loge.target;//访问此特定按钮 } 这是由事件委派完成的。事件将在包装类元素上获得绑定,但将委托给选择器类元素。这就是它的工作原理

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});
和HTML

<div class="wrapper-class">
    <button class="selector-class">
      Click Me!
    </button>
</div>    
注:
包装器类元素可以是任何东西,例如文档、主体或包装器。包装器应该已经存在。然而,选择器不一定需要在页面加载时显示。它可能会稍后出现,事件将在选择器上绑定,不会失败。

请注意,live方法仅适用于某些事件,而不适用于其他事件,如loadedmetadata。请参阅文档中的“注意事项”部分。在此处了解有关事件委派的更多信息:。使用纯javascript/vanilla js实现此目的的任何方法?@Ramswaroop在jQuery中可以完成的任何操作都可以在没有jQuery的情况下完成@戴夫,我想知道为什么你指出的答案没有列在这里。Eli已经明确要求在可能的情况下提供一个没有任何插件的解决方案。这篇文章确实帮助我了解了一个问题,我加载了相同的表单,得到了1,2,4,8,16。。。意见书。我没有使用.live,而是在.load回调中使用了.bind。问题解决了。谢谢这将是一个更好的被接受的答案,因为从特定的表中进行委托比从文档中进行委托更快,搜索区域将更大smaller@msanjay:虽然搜索目标更接近元素是首选,但搜索/速度差异在实践中非常小。你必须每秒点击50000次才能注意到任何东西:谢谢!这解决了我的问题。这个简单的语句是我的问题,事件处理程序只绑定到当前选定的元素;它们必须在代码调用…时存在于页面上。live方法在版本1.7中被弃用,而在版本1.9中被删除。您可以使用代替splitting@EugenKonkov旧浏览器不支持Element.classList。例如,IE<9。这是一篇关于如何使用vanilla脚本而不是jQuery完成任务的好文章-如何使用bubbling?如果单击事件发生在您感兴趣的元素的子元素上,该怎么办?是的,他们没有说documen
t、 它的主体说它的祖先几乎可以是任何东西,你的代码包含1个错误:myElement.append'body';必须是myElement.appendTo'body';。另一方面,如果不需要进一步使用变量myElement,则更简单、更简短的方法是:$'body'。append$,{text:'goToGoogle!'}。bind'click',gotogogle;虽然这个代码片段可以解决这个问题,但它没有解释为什么或者如何回答这个问题。请对你的代码进行解释,因为这确实有助于提高你文章的质量。请记住,您将在将来回答读者的问题,而这些人可能不知道您代码建议的原因。选择器不应包含在$中,因此正确的格式将是$document。单击,选择器,函数{//your code here};如果jQuery对象必须包含字符串或元素对象,您可以直接将其传递给ony参数,那么将其绑定到最近的静态父对象(而不是整个文档)也是毫无意义的。现在不推荐使用委托。不要使用它。我更喜欢这个实现;我只需要设置一个回调,解除绑定不起作用,这只是添加了另一个指向空函数的事件…还可以指定var body=$body.on;是的,但它会为元素创建事件传播。您需要将target添加到特定的动态元素并停止事件传播。如果您在父元素和子元素上绑定了相同的事件,则可以使用event.stoppropagation停止它,您应该将其绑定到最接近的静态父元素,而不是整个文档。
$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});
// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);
<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){
                $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen');
                });

                $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>
const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );
$(document).on("click", "selector", function() {
    // Your code here
});
$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});
<div class="wrapper-class">
    <button class="selector-class">
      Click Me!
    </button>
</div>