Javascript introduces the implementation of event triggers

  • 2020-03-30 03:09:53
  • OfStack

Event triggers can be understood literally and are used to trigger events, but some friends who haven't used them may get confused. Aren't events usually triggered by the user's actual actions on the page? This is not entirely true because some events must be implemented programmatically, such as custom events, and some of the custom events of jQuery's ajax framework must be implemented by event triggers. Of course, in some special cases, it is more convenient to use event triggers to trigger events than the actual actions of the user.


var fireEvent = function(element,event){
 if (document.createEventObject){
  //Internet explorer supports the fireEvent method
  var evt = document.createEventObject();
  return element.fireEvent('on'+event,evt)
 }
 else{
  //Other standard browsers use the dispatchEvent method
  var evt = document.createEvent( 'HTMLEvents' );
  //InitEvent accepts three parameters:
  //Event type, whether it bubbles, whether it blocks the browser's default behavior
  evt.initEvent(event, true, true);  
  return !element.dispatchEvent(evt);
 }
};

The above method is compatible with major browsers to implement the function of event triggers. However, for some encapsulated event processing systems, such as jQuery's event module, it is not so simple and can only be implemented through simulation. I have written a very simple event processing system before, and recently encountered the requirements of custom events, so on the basis of the previous event system to simulate an event trigger, the code is as follows:


/**
 *  Event trigger 
 * @param { Object } DOM The element 
 * @param { String / Object }  The event type  / event object 
 * @param { Array }   Additional parameters passed to the event handler 
 * @param { Boolean }  Whether the bubbling 
 */
trigger : function( elem, event, data, isStopPropagation ){
 var type = event.type || event,
  //Bubbling parent, all the way to document, window
  parent = elem.parentNode || 
   elem.ownerDocument || 
   elem === elem.ownerDocument && win,
  eventHandler = $.data( elem, type + 'Handler' );

 isStopPropagation = typeof data === 'boolean' ? 
  data : (isStopPropagation || false);

 data = data && isArray( data ) ? data : [];

 //Create a custom event object & cake;  
 event = typeof event === 'object' ? 
  event : {
   type : type,
   preventDefault : noop,
   stopPropagation : function(){
    isStopPropagation = true;
   }
  };

 event.target = elem;  
 data.unshift( event );
 if( eventHandler ){
  eventHandler.call( elem, data );
 }
 //Recursively call itself to simulate bubbling
 if( parent && !isStopPropagation ){
  data.shift();
  this.trigger( parent, event, data );
 }
}


The principle of simulation is not difficult, an element is bound to an event handler function, if there is the actual action of triggering the event will execute the corresponding event handler function, so to achieve the function of event trigger as long as the corresponding event handler function is obtained and then executed, this is the most basic.

When an actual event occurs, the browser generates an event object that contains some properties and information about the event. There is no such thing as an event object if no actual event occurs, so the code above also creates an event object that satisfies the most basic functionality.

And event bubbling, if there is no actual events, nature also won't have the behavior of the bubble, so if you want to simulate the function of the bubble, we must constantly look for parent and check whether the binding the same type of event, until to the document and the window, if the structure is complex, the method of recursive calls for performance is expected.

Finally, there is the default behavior of the browser, which I think is quite troublesome to simulate, and I don't know how to implement. For example, the default jump of a tag, I have tested the trigger of jQuery, and it hasn't been implemented, but some other behaviors seem to be introduced in the API manual. After all, this feature is not very important, and I haven't done much research yet.

 

 


Related articles: