We can customize events to achieve more flexible development. Events can be a very powerful tool when used properly. Event-based development has many advantages (introduced later).
Functions with custom events are Event, CustomEvent, and dispatchEvent.
Customize events directly, using the Event constructor:
var event = new Event('build');// Listen for the event.elem.addEventListener('build', function (e) { ... }, false);// Dispatch the event.elem.dispatchEvent(event);CustomEvent can create a more highly customized event, and can also be accompanied by some data. The specific usage is as follows:
var myEvent = new CustomEvent(eventname, options);
Where options can be:
{ detail: { ... }, bubbles: true, cancelable: false}The detail can store some initialization information and can be called when triggered. Other properties are to define whether the event has bubbling and other functions.
Built-in events will be triggered by the browser according to certain operations, and customized events will need to be triggered manually. The dispatchEvent function is used to trigger an event:
element.dispatchEvent(customEvent);
The above code indicates that the customEvent event is triggered on element. Together, use it:
// add an appropriate event listenerobj.addEventListener("cat", function(e) { process(e.detail) });// create and dispatch the eventvar event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}});obj.dispatchEvent(event);Use custom events to pay attention to compatibility issues, but using jQuery is much simpler:
// Bind custom event $(element).on('myCustomEvent', function(){});// Trigger event $(element).trigger('myCustomEvent'); In addition, you can pass more parameter information when triggering a custom event: $( "p" ).on( "myCustomEvent", function( event, myName ) { $( this ).text( myName + ", hi there!" );});$( "button" ).click(function () { $( "p" ).trigger( "myCustomEvent", [ "John" ] );});JavaScript custom events are different from self-customized events such as click and submit. Before describing the benefits of custom events, let’s take a look at an example of custom events:
<div id="testBox"></div>// Create event var evt = document.createEvent('Event');// Define event type evt.initEvent('customEvent', true, true);// Listen to event var obj = document.getElementById('testBox');obj.addEventListener('customEvent', function(){ console.log('customEvent event triggered');}, false);For specific effects, you can check the Demo. Enter obj.dispatchEvent(evt) in the console. You can see that the output "customEvent event triggered" in the console, indicating that the custom event was triggered successfully.
In this process, the createEvent method creates an empty event evt, then uses the initEvent method to define the type of the event as the agreed custom event, and then listens to the corresponding element. Then, use dispatchEvent to trigger the event.
That's right, the mechanism of custom events is like a normal event - listening for events, writing callback operations, and executing callbacks after triggering events. But the difference is that custom events are completely controlled by us, which means that a JavaScript decoupling is implemented. We can flexibly control multiple associated but logically complex operations using the mechanism of custom events.
Of course, you may have guessed that the above code does not take effect in lower versions of IE. In fact, createEvent() is not supported in IE8 and below versions of IE, but there is the private fireEvent() method of IE, but unfortunately, fireEvent only supports the triggering of standard events. Therefore, we can only use one special and simple method to trigger a custom event.
// type is a custom event, such as type = 'customEvent', callback is the callback function actually defined by the developer obj[type] = 0;obj[type]++; obj.attachEvent('onpropertychange', function(event){ if( event.propertyName == type ){ callback.call(obj); }});The principle of this method is actually to add a custom property to the DOM and listen to the propertychange event of the element. When the value of a certain property in the DOM changes, the propertychange callback will be triggered, and then in the callback is determined whether the changed property is our custom property. If so, the callback actually defined by the developer will be executed. This simulates the mechanism of custom events.
In order to enable the mechanism of custom events to cooperate with the listening and simulated triggering of standard events, a complete event mechanism is given here. This mechanism supports the monitoring of standard events and custom events, and removes the listening and simulated triggering operations. It should be noted that in order to make the logic of the code clearer, it is agreed that custom events have the prefix of 'custom' (for example: customTest, customAlert).
/** * @description contains event listening, removal and simulation event triggering, supporting chain calls* */ (function( window, undefined ){ var Ev = window.Ev = window.$ = function(element){ return new Ev.fn.init(element);}; // Ev object construction Ev.fn = Ev.prototype = { init: function(element){ this.element = (element && element.nodeType == 1)? element: document; }, /** * Add event listening* * @param {String} type event type listened* @param {Function} callback callback function*/ add: function(type, callback){ var _that = this; if(_that.element.addEventListener){ /** * @supported For Modern Browers and IE9+ */ _that.element.addEventListener(type, callback, false); } else if(_that.element.attachEvent){ /** * @supported For IE5+ */ // Custom event processing if( type.indexOf('custom') != -1 ){ if( isNaN( _that.element[type] ) ){ _that.element[type] = 0; } var fnEv = function(event){ event = event ? event : window.event if( event.propertyName == type ){ callback.call(_that.element); } }; _that.element.attachEvent('onpropertychange', fnEv); // Store the callback of the bound propertychange on the element to facilitate the removal of event binding if( !_that.element['callback' + callback] ){ _that.element['callback' + callback] = fnEv; } // Standard event handling} else { _that.element.attachEvent('on' + type, callback); } } else { /** * @supported For Others */ _that.element['on' + type] = callback; } return _that; }, /** * Remove event listening* * @param {String} type Event type listened* @param {Function} callback callback function*/ remove: function(type, callback){ var _that = this; if(_that.element.removeEventListener){ /** * @supported For Modern Browers and IE9+ */ _that.element.removeEventListener(type, callback, false); } else if(_that.element.detachEvent){ /** * @supported For IE5+ */ // Custom event processing if( type.indexOf('custom') != -1 ){ // Remove listening to the corresponding custom attributes _that.element.detachEvent('onpropertychange', _that.element['callback' + callback]); // Delete callback for custom events stored on the DOM_that.element['callback' + callback] = null; // Standard event processing} else { _that.element.detachEvent('on' + type, callback); } } else { /** * @supported For Others */ _that.element['on' + type] = null; } return _that; }, /** * Simulate trigger event* @param {String} type Simulate event type of trigger event* @return {Object} Return the current Kjs object*/ trigger: function(type){ var _that = this; try { // Modern browser if(_that.element.dispatchEvent){ // Create event var evt = document.createEvent('Event'); // Define the type of event evt.initEvent(type, true, true); // Trigger the event _that.element.dispatchEvent(evt); // IE } else if(_that.element.fireEvent){ if( type.indexOf('custom') != -1 ){ _that.element[type]++; } else { _that.element.fireEvent('on' + type); } } } catch(e){ }; return _that; }} Ev.fn.init.prototype = Ev.fn; })( window ); Test Case 1 (custom event test) // Test Case 1 (custom event test) // Introduce event mechanism // ...// Catch DOMvar testBox = document.getElementById('testbox');// Callback function 1function triggerEvent(){ console.log('Triggered a custom event customConsole');}// Callback function 2function triggerAgain(){ console.log('Triggered a custom event customConsole');}// Encapsulation testBox = $(testBox);// Bind two callback functions at the same time, supporting chain call to testBox.add('customConsole', triggerEvent).add('customConsole', triggerAgain);The complete code is in Demo.
After opening the Demo, call testBox.trigger('customConsole') in the console to trigger the custom event by itself. You can see that the console outputs two prompts, and then enter testBox.remove('customConsole', triggerAgain) to remove the next listener. At this time, use testBox.trigger('customConsole') to trigger the custom event. You can see that the console only outputs one prompt, that is, the next listener is successfully removed. All functions of the event mechanism work normally.