كيفية تمرير الوسائط إلى وظيفة مستمع addEventListener؟

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

سؤال

الوضع يشبه إلى حد ما-

var someVar = some_other_function();
someObj.addEventListener("click", function(){
    some_function(someVar);
}, false);

المشكلة هي أن قيمة someVar غير مرئي داخل وظيفة المستمع لـ addEventListener, ، حيث من المحتمل أن يتم التعامل معه كمتغير جديد.

هل كانت مفيدة؟

المحلول

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

function() { some_function(someVar); } 

تم إنشاؤه.

ومعرفة ما اذا كان التنبيه يعطيك القيمة التي كنت تبحث عنها، يكون متأكدا من أنه سيكون الوصول إليها في نطاق وظيفة مجهول (إلا إذا كان لديك المزيد من التعليمات البرمجية التي تعمل على نفس المتغير someVar بجانب الدعوة إلى addEventListener)

var someVar; 
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function(){
    some_function(someVar);
}, false);

نصائح أخرى

لماذا لا مجرد الحصول على حجج من السمة الهدف من هذا الحدث؟

مثال:

var someInput = document.querySelector('input');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)
{
  window.alert( evt.target.myParam );
}

وجافا سكريبت هي لغة الموجهة النموذج، تذكر!

وهذه مسألة قديمة ولكنني اعتقدت أن نقدم بديلا باستخدام .bind ES5 ل() - للأجيال القادمة. :)

function some_func(otherFunc, ev) {
    // magic happens
}
someObj.addEventListener("click", some_func.bind(null, some_other_func), false);

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

ويمكنك إضافة وإزالة eventlisteners بحجج بإعلان وظيفة كمتغير.

وmyaudio.addEventListener('ended',funcName=function(){newSrc(myaudio)},false);

وnewSrc هو الأسلوب مع myaudio كمعلمة funcName هو اسم متغير الدالة

ويمكنك إزالة المستمع مع  myaudio.removeEventListener('ended',func,false);

وتماما والسؤال القديم ولكن كان لي نفس القضية اليوم. أنظف وجدت الحل هو استخدام مفهوم الضمادة.

ورمز لذلك:

someObj.addEventListener('click', some_function(someVar));

var some_function = function(someVar) {
    return function curried_func(e) {
        // do something here
    }
}

حسب تسمية وظيفة بالكاري أنها تتيح لك الاتصال Object.removeEventListener إلغاء تسجيل eventListener في وقت لاحق التنفيذ.

ويمكنك ربط فقط كل الحجج اللازمة مع 'ربط':

root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));

في هذه الطريقة سوف تحصل دائما على event، arg1، وغيرها من الاشياء التي تم تمريرها إلى myPrettyHandler.

http://passy.svbtle.com/partial-application- في جافا سكريبت باستخدام-ربط

هل يمكن تمرير somevar من حيث القيمة (وليس بالرجوع) عن طريق ميزة جافا سكريبت المعروف باسم <لأ href = "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" يختلط = " نوفولو noreferrer "> إغلاق :

var someVar='origin';
func = function(v){
    console.log(v);
}
document.addEventListener('click',function(someVar){
   return function(){func(someVar)}
}(someVar));
someVar='changed'

وأو هل يمكن كتابة دالة التفاف الشائعة مثل wrapEventCallback:

function wrapEventCallback(callback){
    var args = Array.prototype.slice.call(arguments, 1);
    return function(e){
        callback.apply(this, args)
    }
}
var someVar='origin';
func = function(v){
    console.log(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'

وهنا wrapEventCallback(func,var1,var2) مثل:

func.bind(null, var1,var2)
يجب أن تكون

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

someObj.addEventListener("click",
                         function(){
                             var newVar = someVar;
                             some_function(someVar);
                         },
                         false);

وواستخدام newVar بدلا من ذلك.

والطريقة الأخرى هي أن يرجع قيمة someVar من some_function() لاستخدامه مرة أخرى في المستمع (كما هو فار المحلي جديد):

var someVar = some_function(someVar);

وهنا بعد وسيلة أخرى (هذا واحد يعمل داخل لحلقات):

var someVar = some_other_function();
someObj.addEventListener("click", 

function(theVar){
    return function(){some_function(theVar)};
}(someVar),

false);

استخدم

   el.addEventListener('click',
    function(){
        // this will give you the id value 
        alert(this.id);    
    },
false);

وإذا كنت ترغب في تمرير أي قيمة مخصصة في هذه الوظيفة مجهولة ثم أسهل طريقة للقيام بذلك هو

 // this will dynamically create property a property
 // you can create anything like el.<your  variable>
 el.myvalue = "hello world";
 el.addEventListener('click',
    function(){
        //this will show you the myvalue 
        alert(el.myvalue);
        // this will give you the id value 
        alert(this.id);    
    },
false);

ويعمل تماما في مشروعي. نأمل أن يكون هذا سيساعد

Function.prototype.bind() هي الطريقة لربط وظيفة مستهدفة بنطاق معين وتحديد اختياري this الكائن داخل الوظيفة الهدف.

someObj.addEventListener("click", some_function.bind(this), false);

أو لالتقاط بعض النطاق المعجمي، على سبيل المثال في حلقة:

someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);

وأخيرا، إذا this المعلمة ليست مطلوبة داخل الوظيفة المستهدفة:

someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);

وأيضا محاولة هذه (. IE8 + كروم أنا لا أعرف لFF):

function addEvent(obj, type, fn) {
    eval('obj.on'+type+'=fn');
}

function removeEvent(obj, type) {
    eval('obj.on'+type+'=null');
}

// Use :

function someFunction (someArg) {alert(someArg);}

var object=document.getElementById('somObject_id') ;
var someArg="Hi there !";
var func=function(){someFunction (someArg)};

// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive

والأمل لا توجد الأخطاء المطبعية: -)

وإرسال الحجج إلى وظيفة رد الاتصال على eventListener يتطلب خلق وظيفة معزولة وتمرير الوسائط إلى أن وظيفة معزولة.

إليك صغيرة لطيفة وظيفة المساعد يمكنك استخدامها. على أساس "مرحبا في العالم" المثال أعلاه).

وشيء واحد أن هناك حاجة أيضا هو الحفاظ على إشارة إلى وظيفة حتى نتمكن من إزالة المستمع نظيفة.

// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running 
// within loops.
//
// The anonymous function returns a closure, that will be executed when 
// the event triggers. And since the arguments were captured, any vars 
// that were sent in will be unique to the function.

function addListenerWithArgs(elem, evt, func, vars){
    var f = function(ff, vv){
            return (function (){
                ff(vv);
            });
    }(func, vars);

    elem.addEventListener(evt, f);

    return f;
}

// Usage:

function doSomething(withThis){
    console.log("withThis", withThis);
}

// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");

// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);

إحدى الطرق هي القيام بذلك باستخدام الوظيفة الخارجية:

elem.addEventListener('click', (function(numCopy) {
  return function() {
    alert(numCopy)
  };
})(num));

تسمى هذه الطريقة لتغليف دالة مجهولة بين قوسين واستدعائها على الفور بـ إيف (تعبير دالة يتم استدعاؤه فورًا)

يمكنك التحقق من مثال يحتوي على معلمتين http://codepen.io/froucher/pen/BoWwgz.

catimg.addEventListener('click', (function(c, i){
  return function() {
    c.meows++;
    i.textContent = c.name + '\'s meows are: ' + c.meows;
  }
})(cat, catmeows));

وعلقت في هذا كما كنت استخدامه في حلقة للعثور على العناصر وإضافة listner إليها. إذا كنت تستخدم ذلك في حلقة، فإن هذا العمل تماما

for (var i = 0; i < states_array.length; i++) {
     var link = document.getElementById('apply_'+states_array[i].state_id);
     link.my_id = i;
     link.addEventListener('click', function(e) {   
        alert(e.target.my_id);        
        some_function(states_array[e.target.my_id].css_url);
     });
}

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

// Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);

// Not Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', function() { myCallback });
someObject.removeEventListener('event', /* can't remove anonymous function */);

وحتى تأخذ ذلك في الاعتبار.

إذا كنت تستخدم ES6 هل يمكن أن تفعل الشيء نفسه كما هو مقترح ولكن قليلا أكثر نظافة:

someObject.addEventListener('event', () => myCallback(params));
    var EV = {
        ev: '',
        fn: '',
        elem: '',
        add: function () {
            this.elem.addEventListener(this.ev, this.fn, false);
        }
    };

    function cons() {
        console.log('some what');
    }

    EV.ev = 'click';
    EV.fn = cons;
    EV.elem = document.getElementById('body');
    EV.add();

//If you want to add one more listener for load event then simply add this two lines of code:

    EV.ev = 'load';
    EV.add();

والنهج التالية عملت بشكل جيد بالنسبة لي. تعديل من <لأ href = "https://github.com/loverajoel/jstips/blob/gh-pages/_posts/en/2016-01-16-passing-arguments-to-callback-functions.md" يختلط = " نوفولو "> هنا .

function callback(theVar) {
  return function() {
    theVar();
  }
}

function some_other_function() {
  document.body.innerHTML += "made it.";
}

var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));
<!DOCTYPE html>
<html>
  <body>
    <button type="button" id="button">Click Me!</button>
  </body>
</html>

    $form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
    function save(data, keyword, name, comment, event) {

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

والجواب التالية صحيحة لكن رمز أدناه لا يعمل في IE8 إذا افترض أنك ضغط الملف شبيبة باستخدام yuicompressor. (في الواقع، لا يزال معظم شعوب الولايات المتحدة باستخدام IE8)

var someVar; 
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
                         function(){
                          some_function(someVar);
                         },
                         false);

وهكذا، يمكننا إصلاح المشكلة المذكورة أعلاه على النحو التالي وأنه يعمل بشكل جيد في جميع المتصفحات

var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);

والأمل، وأنه سيكون من المفيد لبعض واحد الذي هو ضغط ملف شبيبة في بيئة الإنتاج.

وحظا سعيدا !!

وهناك متغير خاص داخل جميع وظائف: <م> الحجج . يمكنك تمرير المعلمات الخاصة كمعلمات المجهول والوصول إليها (من اجل) من خلال الحجج متغير.

مثال:

var someVar = some_other_function();
someObj.addEventListener("click", function(someVar){
    some_function(arguments[0]);
}, false);

والتعليمة البرمجية التالية سار على ما يرام بالنسبة لي (فايرفوكس):

for (var i=0; i<3; i++) {
   element = new ...   // create your element
   element.counter = i;
   element.addEventListener('click', function(e){
        console.log(this.counter);
        ...            // another code with this element
   }, false);
}

وإخراج:

0
1
2

وتحتاج إلى:

newElem.addEventListener('click', {
    handleEvent: function (event) {
        clickImg(parameter);
    }
});

وهذا الحل قد حسن ليبحث

var some_other_function = someVar => function() {
}

someObj.addEventListener('click', some_other_function(someVar));
سوف

وأو ربط المتغيرات تكون جيدة أيضا

وجميل بديل سطر واحد

element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) {

 //some action...

}

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

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

وفي الأصل، كانت جميع الدالة ReadFile () داخل readFiles وظيفة (). هذا سبب القضايا الاستطلاعية غير متزامن.

    function readFiles(input) {
      if (input.files) {
        for(i=0;i<input.files.length;i++) {

          var filename = input.files[i].name;

          if ( /\.(jpe?g|jpg|png|gif|svg|bmp)$/i.test(filename) ) {
            readFile(input.files[i],filename);
          }
       }
      }
    } //end readFiles



    function readFile(file,filename) {
            var reader = new FileReader();

            reader.addEventListener("load", function() { alert(filename);}, false);

            reader.readAsDataURL(file);

    } //end readFile

والبديلة الأخرى، ربما ليس أنيقة مثل استخدام مأزق، ولكن لم يصح للأحداث في حلقة

for (var key in catalog){
    document.getElementById(key).my_id = key
    document.getElementById(key).addEventListener('click', function(e) {
        editorContent.loadCatalogEntry(e.srcElement.my_id)
    }, false);
}

تم اختباره لملحقات جوجل كروم ويجب أن يتم استبداله ربما e.srcElement التي كتبها e.source في المتصفحات الأخرى

ولقد وجدت هذا الحل باستخدام تعليق أرسلت بواسطة Imatoria لكنني لا يمكن وضع علامة أنه من المفيد، وذلك لأن ليس لدي ما يكفي من سمعة: D

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