JQueryを使用して動的に挿入する要素にonclickイベントをバインドしたい
ただし、バインドされた関数は実行されません。この例が機能しない理由と、正しく実行する方法を教えていただければ幸いです。
<!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" xml:lang="da" lang="da">
<head>
<title>test of click binding</title>
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
jQuery(function(){
close_link = $('<a class="" href="#">Click here to see an alert</a>');
close_link.bind("click", function(){
alert('hello from binded function call');
//do stuff here...
});
$('.add_to_this').append(close_link);
});
</script>
</head>
<body>
<h1 >Test of click binding</h1>
<p>problem: to bind a click event to an element I append via JQuery.</p>
<div class="add_to_this">
<p>The link is created, then added here below:</p>
</div>
<div class="add_to_this">
<p>Another is added here below:</p>
</div>
</body>
</html>
編集:メソッドを挿入する2つの要素を含むように例を編集しました。その場合、alert()
呼び出しは実行されません。 (コメントで指摘してくれた@Daffに感謝)
最初の問題は、複数の要素を持つjQueryセットでappendを呼び出すと、追加する要素のクローンがそれぞれに対して作成されるため、添付イベントオブザーバが失われることです。
別の方法は、各要素のリンクを作成することです:
function handler() { alert('hello'); }
$('.add_to_this').append(function() {
return $('<a>Click here</a>').click(handler);
})
別の潜在的な問題は、要素がDOMに追加される前にイベントオブザーバがアタッチされることです。これに何か言いたいことがあるかどうかはわかりませんが、その振る舞いは未定と考えられるかもしれません。より確実なアプローチは、おそらく次のとおりです。
function handler() { alert('hello'); }
$('.add_to_this').each(function() {
var link = $('<a>Click here</a>');
$(this).append(link);
link.click(handler);
});
これらのメソッドはすべて非推奨です。 on
メソッドを使用して問題を解決する必要があります。
動的に追加された要素をターゲットにしたい場合は、使用する必要があります
$(document).on('click', selector-to-your-element , function() {
//code here ....
});
これは、非推奨の.live()
メソッドを置き換えます。
Liveメソッドはどうですか?
$('.add_to_this a').live('click', function() {
alert('hello from binded function call');
});
それでも、あなたがやったことはうまくいくはずです。 別の投稿 があり、かなり似ています。
パーティーに少し遅れましたが、jQueryイベントハンドラーでよくある誤解を解消しようと考えました。 jQuery 1.7では、非推奨の.on()
の代わりに.live()
を使用して、イベントハンドラーが割り当てられた後の任意の時点で動的に作成される要素にイベントハンドラーを委任する必要があります。
ただし、構文が少し異なるため、live
をon
に切り替えるのは簡単ではありません。
新しい方法(例1):
$(document).on('click', '#someting', function(){
});
非推奨のメソッド(例2):
$('#something').live(function(){
});
上記のように、違いがあります。ツイストは.on()
であり、セレクターをjQuery関数自体に渡すことで、実際に.live()
と同様に呼び出すことができます。
例3:
$('#something').on('click', function(){
});
ただし、例1のように$(document)
を使用しないと、例3は動的に作成された要素に対して機能しません。動的な委任が不要な場合、例3はまったく問題ありません。
すべてに$(document).on()を使用する必要がありますか?
それは機能しますが、動的な委任が必要ない場合は、例1がブラウザからのより多くの作業を必要とするため、例3を使用する方が適切です。パフォーマンスに実際の影響はありませんが、使用に最も適切な方法を使用することは理にかなっています。
動的な委任が不要な場合、.click()の代わりに.on()を使用する必要がありますか?
必ずしも。以下は、例3のショートカットです。
$('#something').click(function(){
});
上記は完全に有効であるため、動的な委任が不要な場合にどの方法を使用するかは、実際のところ個人の好みの問題です。
参照:
このことを考慮:
jQuery(function(){
var close_link = $('<a class="" href="#">Click here to see an alert</a>');
$('.add_to_this').append(close_link);
$('.add_to_this').children().each(function()
{
$(this).click(function() {
alert('hello from binded function call');
//do stuff here...
});
});
});
すべての特定の要素に添付するため、機能します。リンクがDOMに追加された後、DOMでJQuery要素として追加された要素を明示的に選択し、クリックイベントをそれにバインドする方法を見つける必要があるのはこのためです。
最良の方法は、おそらく提案されているように、ライブメソッドを介して特定のクラスにバインドすることです。
要素とともにクリックイベントを作成することが可能であり、時には必要です。これは、たとえば、セレクタベースのバインディングがオプションではない場合です。重要な部分は、単一の要素で.replaceWith()
を使用することで Tobias が言っていた問題を回避することです。これは概念実証にすぎないことに注意してください。
<script>
// This simulates the object to handle
var staticObj = [
{ ID: '1', Name: 'Foo' },
{ ID: '2', Name: 'Foo' },
{ ID: '3', Name: 'Foo' }
];
staticObj[1].children = [
{ ID: 'a', Name: 'Bar' },
{ ID: 'b', Name: 'Bar' },
{ ID: 'c', Name: 'Bar' }
];
staticObj[1].children[1].children = [
{ ID: 'x', Name: 'Baz' },
{ ID: 'y', Name: 'Baz' }
];
// This is the object-to-html-element function handler with recursion
var handleItem = function( item ) {
var ul, li = $("<li>" + item.ID + " " + item.Name + "</li>");
if(typeof item.children !== 'undefined') {
ul = $("<ul />");
for (var i = 0; i < item.children.length; i++) {
ul.append(handleItem(item.children[i]));
}
li.append(ul);
}
// This click handler actually does work
li.click(function(e) {
alert(item.Name);
e.stopPropagation();
});
return li;
};
// Wait for the dom instead of an ajax call or whatever
$(function() {
var ul = $("<ul />");
for (var i = 0; i < staticObj.length; i++) {
ul.append(handleItem(staticObj[i]));
}
// Here; this works.
$('#something').replaceWith(ul);
});
</script>
<div id="something">Magical ponies ♥</div>
function load_tpl(selected=""){
$("#load_tpl").empty();
for(x in ds_tpl){
$("#load_tpl").append('<li><a id="'+ds_tpl[x]+'" href="#" >'+ds_tpl[x]+'</a></li>');
}
$.each($("#load_tpl a"),function(){
$(this).on("click",function(e){
alert(e.target.id);
});
});
}
私はそれをする良い方法を信じています:
$('#id').append('<a id="#subid" href="#">...</a>');
$('#subid').click( close_link );