Adding and Removing Event Listeners with parameters

后端 未结 4 412
我在风中等你
我在风中等你 2020-12-09 18:31

I am writing a vanilla JavaScript tool, that when enabled adds event listeners to each of the elements passed into it.

I would like to do something

相关标签:
4条回答
  • 2020-12-09 18:49

    This can be done quite easily, just not as you have it right now.

    Instead of trying to add and remove random anonymouse functions, you need to add or remove a function that handles the execution of your other functions.

    var
        // Here we are going to save references to our events to execute
        cache = {},
    
        // Create a unique string to mark our elements with
        expando = String( Math.random() ).split( '.' )[ 1 ],
    
        // Global unique ID; we use this to keep track of what events to fire on what elements
        guid = 1,
    
        // The function to add or remove. We use this to handler all of other 
        handler = function ( event ) {
    
            // Grab the list of functions to fire
            var handlers = ( cache[ this[ expando ] ] && cache[ this[ expando ] ][ event.type ] ) || false;
    
            // Make sure the list of functions we have is valid
            if ( !handlers || !handlers.length ) {
                return;
            }
    
            // Iterate over our individual handlers and call them as we go. Make sure we remeber to pass in the event Object
            handlers.forEach( function ( handler ) {
                handler.call( this, event );
            });
    
        },
    
        // If we want to add an event to an element, we use this function
        add = function ( element, type, fn ) {
    
            // We test if an element already has a guid assigned
            if ( !element[ expando ] ) {
                element[ expando ] = guid++;
            }
    
            // Grab the guid number
            var id = element[ expando ];
    
            // Make sure the element exists in our global cache
            cache[ id ] = cache[ id ] || {};
    
            // Grab the Array that we are going to store our handles in
            var handlers = cache[id ][ type ] = cache[ id ][ type ] || [];
    
           // Make sure the handle that was passed in is actually a function
            if ( typeof fn === 'function' ) {
                handlers.push( fn );
            }
    
            // Bind our master handler function to the element
            element.addEventListener( type, handler, false );
    
        };
    
    // Add a click event to the body element
    add( document.body, 'click', function ( event ) {
        console.log( 1 );
    });
    

    This is just a cut down version of what I've written before, but you can get the gist of it I hope.

    0 讨论(0)
  • 2020-12-09 18:56

    This is invalid:

    arr[i].el.addEventListener('click', do_something(arr[i]));
    

    The listener must be a function reference. You cannot specify parameters at the time of listener assignment. A handler function will always be called with the event being passed as the first argument. To pass other arguments, you can wrap your listener into an anonymous function like so:

    elem.addEventListener('click', function(event) {
      do_something( ... )
    }
    

    To be able to remove via removeEventListener you just name the handler function:

    function myListener(event) {
      do_something( ... );
    }
    
    elem.addEventListener('click', myListener);
    

    To have access other variables in the handler function, you can use closures. E.g.:

    function someFunc() {
      var a = 1,
          b = 2;
    
      function myListener(event) {
        do_something(a, b);
      }
    
      elem.addEventListener('click', myListener);
    }
    
    0 讨论(0)
  • 2020-12-09 19:06

    To 'addEventListener' with some parameters, you can use the following code:

    {
       myButton.addEventListener("click",myFunction.bind(null,event,myParameter1,myParameter2)); 
    }
    

    And the function 'myFunction' should be something like this:

    {
       function myFunction(event, para1, para2){...}
    }
    
    0 讨论(0)
  • 2020-12-09 19:07

    To pass arguments to event handlers bind can be used or handler returning a function can be used

    // using bind
    var do_something = function (obj) {
      // do something
    }
    
    for (var i = 0; i < arr.length; i++) {
      arr[i].el.addEventListener('click', do_something.bind(this, arr[i]))
    }
    
    
    // using returning function
    var do_something = obj => e {
      // do something
    }
    
    for (var i = 0; i < arr.length; i++) {
      arr[i].el.addEventListener('click', do_something(arr[i]))
    }
    

    But in both the cases to remove the event handlers it is not possible as bind will give a new referenced function and returning function also does return a new function every time for loop is executed.

    To handle this problem we need to store the references of the functions in an Array and remove from that.

    // using bind
    var do_something = function (obj) {
      // do something
    }
    var handlers = []
    
    for (var i = 0; i < arr.length; i++) {
      const wrappedFunc = do_something.bind(this, arr[i])
      handlers.push(wrappedFunc)
      arr[i].el.addEventListener('click', wrappedFunc);
    }
    //removing handlers
    function removeHandlers() {
      for (var i = 0; i < arr.length; i++) {
        arr[i].el.removeEventListener('click', handlers[i]);
      }
      handlers = []
    }
    
    0 讨论(0)
提交回复
热议问题