هل هناك أي طريقة لمنع "هذا" من التغيير عندما أقوم بلف وظيفة؟

StackOverflow https://stackoverflow.com/questions/400968

  •  03-07-2019
  •  | 
  •  

سؤال

أريد أن تقوم جميع الأزرار بتنفيذ إجراء قبل وبعد حدث النقر العادي.لذلك توصلت إلى فكرة "رائعة" تتمثل في تكرار كل هذه العناصر وإنشاء وظيفة مجمعة.

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

هل يعرف أحد طريقة أفضل للقيام بنفس الشيء؟أو طريقة جيدة للحفاظ على قيم "هذا" المقصودة أصلاً؟

كما يمكنك أن تتخيل، لا أريد تعديل أي من أكواد معالج الأحداث الموجودة في أزرار الهدف.

شكرا لك مقدما.

ملاحظة: المتصفح المستهدف هو IE6 والإصدارات الأحدث، ووظيفة المتصفح المتقاطع غير مطلوبة

<!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">
<script language="javascript" type="text/javascript">
    function btnWrap_onClick()
    {
        var btns = document.getElementsByTagName("button");
        for( var i = 0; i < btns.length; i++)
        {
            var btn = btns[i];

            // handle wrap button differerntly
            if( "btnWrap" == btn.id)
            {
                btn.disabled = true;
                continue; // skip this button
            }

            // wrap it
            var originalEventHandler = btn.onclick;
            btn.onclick = function()
            {
                alert("Starting event handler");
                originalEventHandler();
                alert("Finished event handler");
            }
        }

        alert("Buttons wrapped successfully");
    }
</script>
<body>
    <p>
    <button id="TestButton1" onclick="alert(this.id);">TestButton1</button>
    <button id="TestButton2" onclick="alert(this.id);">TestButton2</button>
    </p>
    <button id="btnWrap" onclick="btnWrap_onClick();">Wrap Event Handlers</button>
</body>
</html>
هل كانت مفيدة؟

المحلول

يحب بول ديكسون وقال، يمكنك استخدام يتصل ولكن أقترح عليك استخدام يتقدم بدلاً من.

ومع ذلك، فإن سبب إجابتي هو أنني وجدت خطأً مزعجًا: أنت في الواقع تستبدل جميع معالجات الأحداث الخاصة بك بمعالج الأحداث للزر الأخير. لا أعتقد أن هذا ما كنت تقصده، أليس كذلك؟(تَلمِيح:أنت تقوم باستبدال قيمة originalEventHandler في كل تكرار)

ستجد في الكود أدناه حلاً فعالاً عبر المتصفحات:

function btnWrap_onClick()
{
    var btns = document.getElementsByTagName("button");
    for( var i = 0; i < btns.length; i++)
    {
        var btn = btns[i];

        // handle wrap button differerntly
        if( "btnWrap" == btn.id)
        {
            btn.disabled = true;
            continue; // skip this button
        }

        // wrap it

        var newOnClick = function()
        {
            alert("Starting event handler");
            var src=arguments.callee;
            src.original.apply(src.source,arguments);
            alert("Finished event handler");
        }
        newOnClick.original = btn.onclick; // Save original onClick
        newOnClick.source = btn; // Save source for "this"
        btn.onclick = newOnClick; //Assign new handler
    }
alert("Buttons wrapped successfully");
}

أولاً أقوم بإنشاء وظيفة مجهولة جديدة وتخزينها في المتغير newOnClick.بما أن الوظيفة هي كائن، فيمكنني إنشاء خصائص على كائن الوظيفة مثل أي كائن آخر.أنا استخدم هذا لإنشاء الخاصية إبداعي هذا هو معالج onclick الأصلي، و مصدر هذا هو العنصر المصدر الذي سيكون هذا عندما يتم استدعاء المعالج الأصلي.

داخل الوظيفة المجهولة أحتاج إلى الحصول على مرجع للوظيفة حتى أتمكن من الحصول على قيمة الخصائص إبداعي و مصدر.نظرًا لأن الوظيفة المجهولة ليس لها اسم أستخدمه الوسيطات.callee (والذي تم دعمه منذ MSIE5.5) للحصول على هذا المرجع وتخزينه في المتغير src.

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

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

نصائح أخرى

يمكنك استخدام ال يتصل طريقة لحل الربط، على سبيل المثال. originalEventHandler.call(btn);

وبدلاً من ذلك، يمكن لمكتبة مثل النموذج الأولي أن تساعد - إنها ربط تتيح لك الطريقة إنشاء دالة جديدة مرتبطة بكائن محدد، لذا فقد قمت بتعريف originalEventHandler كـ var originalEventHandler = btn.onclick.bind(btn);

أخيرًا، للحصول على معلومات أساسية جيدة عن المشكلات الملزمة، راجع أيضًا الخروج من المواقف الملزمة في جافا سكريبت

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top