جاوااسکریپت - چگونه میتوانم رویدادها را به عناصر HTML داینامیک با jQuery متصل کنم؟
فرض کنید من کدی در jQuery دارم که یک هندلر رویداد به تمام عناصر با کلاس .myclass متصل میکند.
به عنوان مثال:
$(function(){
$(".myclass").click( function() {
// do something
});
});
و HTML من ممکن است به صورت زیر باشد:
<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>
این بدون مشکل کار میکند. با این حال، در نظر بگیرید اگر عناصر .myclass در آینده به صفحه نوشته شوند.
به عنوان مثال:
<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
$("#anchor1").click( function() {
$("#anchor1").append('<a class="myclass" href="#">test4</a>');
});
});
</script>
در این حالت، لینک test4 زمانی ایجاد میشود که کاربر روی a#anchor1 کلیک کند.
لینک test4 دارای هندلر click() مرتبط نیست، حتی اگر class="myclass" را داشته باشد.
اصولاً، من میخواهم هندلر click() را یک بار بنویسم و آن برای هر دو نوع محتوا اعمال شود: محتوایی که هنگام بارگذاری صفحه حاضر است و محتوایی که بعداً از طریق AJAX/DHTML آورده میشود. ایدهای دارید که چگونه میتوانم این مشکل را حل کنم؟
پاسخ شماره ۱
من یک پاسخ جدید اضافه میکنم تا تغییرات در نسخههای بعدی jQuery را منعکس کنم. متد .live() از jQuery 1.7 منسوخ شده است.
از http://api.jquery.com/live/
از جومری 1.7 به بعد، متد .live() منسوخ شده است. از .on() برای وصل کردن مدیریتکنندههای رویداد استفاده کنید. کاربران نسخههای قدیمیتر جومری باید ترجیحاً از .delegate() به جای .live() استفاده کنند.
برای jQuery 1.7+ شما میتوانید یک هندلر رویداد به یک عنصر والد با استفاده از .on() متصل کنید و یک سلکتور ترکیب شده با 'myclass' را به عنوان آرگومان منتقل کنید.
به http://api.jquery.com/on/ مراجعه کنید
پس به جای...
$(".myclass").click( function() {
// do something
});
شما میتوانید بنویسید...
$('body').on('click', 'a.myclass', function() {
// do something
});
این برای تمام تگهای a که 'myclass' در بدن آنها وجود دارد کار خواهد کرد، چه قبلاً موجود باشند و چه بعداً به صورت پویا اضافه شوند.
تگ body در اینجا استفاده شده است زیرا مثال هیچ تگ ایستا و نزدیکتری نداشت، اما هر تگ والد موجود در زمان فراخوانی متد .on کار خواهد کرد. برای مثال، یک تگ ul برای یک لیست که عناصر پویا به آن اضافه خواهند شد، به این شکل خواهد بود:
$('ul').on('click', 'li', function() {
alert( $(this).text() );
});
تا زمانی که تگ ul وجود داشته باشد، این کار خواهد کرد (نیازی به وجود المانهای li نیست).
پاسخ شماره ۲
گاهی انجام این کار (پاسخ با بیشترین رأی) همیشه کافی نیست:
$('body').on('click', 'a.myclass', function() {
// do something
});
این میتواند مسئلهساز باشد به دلیل ترتیب اجرای کنترلکنندههای رویداد. اگر خودتان این کار را انجام میدهید و باعث بروز مشکل میشود به خاطر ترتیبی که در آن رسیدگی میشود... همیشه میتوانید آن را داخل یک تابع بپیچید، که وقتی فراخوانی میشود، «شنونده» را تازه میکند.
به عنوان مثال:
function RefreshSomeEventListener() {
// Remove handler from existing elements
$("#wrapper .specific-selector").off();
// Re-add event handler for all matching elements
$("#wrapper .specific-selector").on("click", function() {
// Handle event.
}
}
چون این یک تابع است، هر وقت که شنوندهام را به این صورت تنظیم میکنم، معمولاً آن را هنگام آماده شدن سند فراخوانی میکنم:
$(document).ready(function() {
// Other ready commands / code
// Call our function to setup initial listening
RefreshSomeEventListener();
});
سپس، هر زمان که عنصری بهطور پویا اضافه میکنید، دوباره آن متد را فراخوانی کنید:
function SomeMethodThatAddsElement() {
// Some code / AJAX / whatever.. Adding element dynamically
// Refresh our listener, so the new element is taken into account
RefreshSomeEventListener();
}
امیدوارم این کمک کند!
با احترام،
پاسخ شماره ۳
بعد از jQuery 1.7، روشهای ترجیحی .on() و .off() هستند
پاسخ شون یک مثال را نشان میدهد.
اکنون منسوخ شده:
از توابع jQuery
.live()و.die()استفاده کنید. در jQuery 1.3.x موجود هستند.از مستندات:
برای نمایش متن هر پاراگراف در یک جعبه هشدار هر زمان که روی آن کلیک شود:
$("p").live("click", function(){ alert( $(this).text() ); });
همچنین، پلاگین livequery این کار را انجام میدهد و از رویدادهای بیشتری پشتیبانی میکند.
