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

我有一些代码,我循环浏览页面上的所有选择框并将.hover事件绑定到它们,以便在mouse on/off上对它们的宽度进行一些摆弄。

这发生在页面准备好并工作得很好。

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

我找到了这个插件(jQuery实时查询插件),但在我使用插件向页面添加另一个5k之前,我想看看是否有人知道直接使用jQuery或通过其他选项执行此操作的方法。

1046488 次浏览

您可以在创建对象时将事件添加到对象中。如果您在不同时间将相同的事件添加到多个对象,那么创建命名函数可能是最好的选择。

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开始您应该使用#0并填充选择器参数:

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

说明:

这称为事件委托并按照以下方式工作。事件附加到应该处理的元素的静态父级(staticAncestors)。每次事件触发此元素或后代元素之一时,都会触发此jQuery处理程序。然后,处理程序检查触发事件的元素是否与您的选择器(dynamicChild)匹配。当有匹配时,将执行您的自定义处理程序函数。


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

$(selector).live( eventName, function(){} );

然而,live()在1.7中被弃用,转而支持on(),并在1.9中完全删除。live()签名:

$(selector).live( eventName, function(){} );

…可以用以下#0签名替换:

$(document).on( eventName, selector, function(){} );

例如,如果您的页面正在动态创建类名为dosomething的元素,您将把事件绑定到已经存在的父节点(这是问题的核心,您需要绑定到存在的东西,不要绑定到动态内容),这可以是(也是最简单的选择)document。但请记住#1可能不是最有效的选择

$(document).on('mouseover mouseout', '.dosomething', function(){// what you want to happen when mouseover and mouseout// occurs on elements that match '.dosomething'});

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

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

将适用于

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

尝试使用.live()而不是.bind();在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>

#0的留档中有一个很好的解释。

简而言之:

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

因此,在下面的示例中,#dataTable tbody tr必须在生成代码之前存在。

$("#dataTable tbody tr").on("click", function(event){console.log($(this).text());});

如果将新的超文本标记语言注入页面,最好使用委托事件来附加事件处理程序,如下所述。

委托的活动的优点是它们可以处理稍后添加到文档中的后代元素中的事件。例如,如果表存在,但行是使用代码动态添加的,以下将处理它:

$("#dataTable tbody").on("click", "tr", function(event){console.log($(this).text());});

除了能够处理尚未创建的后代元素上的事件之外,委托事件的另一个优点是,当必须监控许多元素时,它们的开销可能要低得多。在tbody中有1,000行的数据表上,第一个代码示例将处理程序附加到1,000个元素。

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

备注:委托事件不适用于SVG

这是一个没有任何库或插件的纯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);

hasClass在哪里

function hasClass(elem, className) {return elem.className.split(' ').indexOf(className) > -1;}

现场演示

归功于Dave和Sime Vidas

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

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

下面嵌入了相同的jsfiddle Live演示:

function hasClass(elem, className) {return elem.classList.contains(className);}
document.addEventListener('click', function(e) {if (hasClass(e.target, 'bu')) {alert('bu');document.querySelector('.bu').innerHTML = '<div class="bu">Bu<div class="tu">Tu</div></div>';} else if (hasClass(e.target, 'test')) {alert('test');} else if (hasClass(e.target, 'tu')) {alert('tu');}
}, false);
.test,.bu,.tu {border: 1px solid gray;padding: 10px;margin: 10px;}
<div class="test">Test<div class="bu">Bu</div>test</div>

另一种解决方案是在创建元素时添加侦听器。不是将侦听器放在主体中,而是在创建元素的那一刻将侦听器放在元素中:

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});

在事件绑定时的任何p不存在,如果您的页面是动态创建元素,类名为按钮,您将将事件绑定到已经存在的父级

$(document).ready(function(){//Particular Parent chield click$(".buttons").on("click","button",function(){alert("Clicked");});  
//Dynamic event bind on button class$(document).on("click",".button",function(){alert("Dymamic Clicked");});$("input").addClass("button");});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><div class="buttons"><input type="button" value="1"><button>2</button><input type="text"><button>3</button><input type="button" value="5"></div><button>6</button>

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

单一元素:

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

子元素:

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

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

我注意到:

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

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

注意元素放置的“MAIN”类,例如,

<div class="container"><ul class="select"><li> First</li><li>Second</li></ul></div>

在上述场景中,jQuery将监视的MAIN对象是“容器”。

然后你基本上会在容器下有元素名称,例如ulliselect

$(document).ready(function(e) {$('.container').on( 'click',".select", function(e) {alert("CLICKED");});});

试着用这种方式——

$(document).on( 'click', '.click-activity', function () { ... });

您可以使用

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

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

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

见:jQuery代理事件

使用jQueryhttp://api.jquery.com/on/.on()方法将事件处理程序附加到live元素。

此外,从版本1.9.live()中删除了方法。

您可以在使用#0动态创建时将事件附加到元素。

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

function handleDynamicElementEvent(event) {console.log(event.type, this.value)}// create and attach event to dynamic elementjQuery("<select>", {html: $.map(Array(3), function(_, index) {return new Option(index, index)}),on: {change: handleDynamicElementEvent}}).appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

创建元素和绑定事件的另一种灵活解决方案(来源

// creating a dynamic element (container div)var $div = $("<div>", {id: 'myid1', class: 'myclass'});
//creating a dynamic buttonvar $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);

注意:这将为每个元素创建一个事件处理程序实例(在循环中使用时可能会影响性能)

这就是动态创建的元素不响应点击的原因:

var body = $("body");var btns = $("button");var btnB = $("<button>B</button>");// `<button>B</button>` is not yet in the document.// Thus, `$("button")` gives `[<button>A</button>]`.// Only `<button>A</button>` gets a click listener.btns.on("click", function () {console.log(this);});// Too late for `<button>B</button>`...body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><button>A</button>

作为一种解决方法,您必须监听所有点击并检查源元素:

var body = $("body");var btnB = $("<button>B</button>");var btnC = $("<button>C</button>");// Listen to all clicks and// check if the source element// is a `<button></button>`.body.on("click", function (ev) {if ($(ev.target).is("button")) {console.log(ev.target);}});// Now you can add any number// of `<button></button>`.body.append(btnB);body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><button>A</button>

这被称为事件委托。好消息,这是jQuery中的内置功能:-)

var i = 11;var body = $("body");body.on("click", "button", function () {var letter = (i++).toString(36).toUpperCase();body.append($("<button>" + letter + "</button>"));});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><button>A</button>

<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>

我正在寻找一个解决方案,让$.bind$.unbind在动态添加的元素中没有问题。

由于on()使附加事件的技巧,为了在我来到的那些上创建一个虚假的解除绑定:

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});

我更喜欢以模块化函数的方式部署事件侦听器,而不是编写document级事件侦听器的脚本。所以,我喜欢下面。请注意,您不能过度订阅具有相同事件侦听器的元素,因此不要担心多次附加侦听器-只有一个棒。

var iterations = 4;var button;var body = document.querySelector("body");
for (var i = 0; i < iterations; i++) {button = document.createElement("button");button.classList.add("my-button");button.appendChild(document.createTextNode(i));button.addEventListener("click", myButtonWasClicked);body.appendChild(button);}
function myButtonWasClicked(e) {console.log(e.target); //access to this specific button}

这是由事件委托完成的。事件将在包装类元素上绑定,但将委托给选择器类元素。这就是它的工作原理。

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

超文本标记语言

<div class="wrapper-class"><button class="selector-class">Click Me!</button></div>

#注意:包装类元素可以是任何东西,例如。文档、正文或您的包装器。Wrapper应该已经存在。但是,selector不一定需要在页面加载时呈现。它可能会稍后出现,事件将绑定在selector没有失败上。