javascript - tutorial - what is jquery




ربط الحدث على العناصر التي تم إنشاؤها ديناميكيا؟ (14)

لدي القليل من التعليمة البرمجية حيث أقوم بالتكرار خلال جميع مربعات الاختيار على الصفحة .hover حدث .hover لهم للقيام .hover الشيء مع عرضهم على mouse on/off .

هذا يحدث على صفحة جاهزة ويعمل على ما يرام.

المشكلة التي لدي هي أن أي مربعات مختارة أقوم بإضافتها عبر Ajax أو DOM بعد الحلقة الأولية لن يكون لها حدث محدد.

لقد عثرت على هذا المكون الإضافي ( jQuery Live Query Plugin ) ، ولكن قبل إضافة 5 آلاف أخرى إلى صفحاتي مع مكون إضافي ، أريد معرفة ما إذا كان أي شخص يعرف طريقة للقيام بذلك ، إما باستخدام jQuery مباشرة أو من خلال خيار آخر.


ربط الحدث على العناصر التي تم إنشاؤها ديناميكيًا

عنصر واحد:

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

عنصر الطفل:

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

لاحظ * المضافة. سيتم تشغيل الحدث لجميع أطفال هذا العنصر.

وقد لاحظت أن:

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

لم يعد يعمل أكثر من ذلك ، لكنه كان يعمل من قبل. أنا أستخدم jQuery من Google CDN ، ولكن لا أعرف ما إذا كانوا قد غيروه.


أفضل استخدام المحدد وأطبقه على المستند.

هذا يربط نفسه على الوثيقة وسيكون قابلا للتطبيق على العناصر التي سيتم تقديمها بعد تحميل الصفحة.

فمثلا:

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

استخدم طريقة .on() jQuery on() لإرفاق معالجات الأحداث لعنصر مباشر.

أيضا اعتبارا من الإصدار 1.9 .live() تتم إزالة الأسلوب.


المنطق وراء هذا الشيء هو وجود العنصر حيث تحتاج إلى ربط الحدث الخاص بك. إذا كنت تعتقد أن العنصر سيأتي في المستقبل في وقت ما أو بعد مرور بعض الوقت بعد تحميل موقع الويب الخاص بك ، فمن الأفضل استخدام تفويض الحدث وهذا الخط البسيط من التعليمات البرمجية يكفي.

 $(document).on( 'eventName', '.elementName', function () { ... do your work 
}); 

قد يكون eventName هنا أي حدث مثل النقر أو تمرير الماوس أو mouseleave أو الإدخال أو التغيير ...


حاول استخدام .live() بدلاً من .bind() ؛ سيتم ربط .live() في مربع الاختيار بعد تنفيذ طلب Ajax.


حل آخر هو إضافة المستمع عند إنشاء العنصر. بدلاً من وضع المستمع في الجسم ، تضع المستمع في العنصر في اللحظة التي تقوم بإنشائه فيها:

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

عرض حي

الائتمان يذهب إلى ديف وسيمي فيداس

باستخدام JS أكثر حداثة ، hasClass يمكن أن تنفذ على النحو التالي:

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

هناك تفسير جيد في وثائق on() .

باختصار:

تكون معالجات الأحداث مرتبطة فقط بالعناصر المحددة حاليًا ؛ يجب أن تكون موجودة على الصفحة في الوقت الذي يجعل التعليمات البرمجية المكالمة إلى .on() .

وبالتالي في المثال التالي #dataTable 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());
});

بالإضافة إلى قدرتها على التعامل مع الأحداث على العناصر المتفرعة التي لم يتم إنشاؤها بعد ، فإن ميزة أخرى للأحداث المفوضة هي قدرتها على خفض النفقات العامة عندما يجب مراقبة العديد من العناصر. في جدول البيانات مع 1000 صف في tbody الخاص به ، يربط المثال الأول من التعليمات البرمجية معالج إلى 1000 عنصر.

يقوم نهج الأحداث المفوَّضة (مثال الكود الثاني) بإرفاق معالج حدث إلى عنصر واحد فقط ، هو tbody ، والحدث لا يحتاج إلا إلى tbody مستوى واحد (من tr إلى tbody ).

ملاحظة: لا تعمل الأحداث المفوَّضة لـ SVG .


يمكنك إرفاق حدث بعنصر عندما يتم إنشاؤه ديناميكيًا باستخدام jQuery(html, attributes) .

اعتبارًا من jQuery 1.8 ، يمكن استخدام أي أسلوب مثيل jQuery (طريقة jQuery.fn ) كخاصية للكائن الذي تم تمريره إلى المعلمة الثانية:

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<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>


يمكنك إضافة أحداث إلى الكائنات عند إنشائها. إذا كنت تضيف نفس الأحداث إلى كائنات متعددة في أوقات مختلفة ، فقد يكون إنشاء وظيفة مسماة هو الطريق الذي يجب اتباعه.

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 */ )
;

يمكنك استخدام الأسلوب 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>

يمكنك ببساطة التفاف مكالمة ربط الحدث الخاصة بك إلى وظيفة ثم استدعاءها مرتين: بمجرد إعداد المستند ومرة ​​واحدة بعد الحدث الذي يضيف عناصر DOM جديدة. إذا قمت بذلك ، فستحتاج إلى تجنب ربط الحدث نفسه مرتين على العناصر الموجودة ، بحيث تحتاج إما إلى إلغاء الأحداث الموجودة أو ربط (أفضل) فقط بعناصر DOM التي تم إنشاؤها حديثًا. سيبدو الرمز شيئًا كالتالي:

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

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

// ... add elements ...
addCallbacks($(".myNewElements"))

حل أكثر مرونة لإنشاء عناصر وربط الأحداث ( source )

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




unobtrusive-javascript