Source code analysis

On, once and off can all be called in chain mode

on

  1. In order totype: [handler]It’s stored in an instance, so it’s the sametypeYes you can bind more than onehandler

once

The task is marked as a one-time task that is removed from the array after execution

off

  1. ifhandler*That will betypeCorresponding to allhandlerdelete
deleteClears objects directly instead of setting []delete this._event_[ type ]
// undefined
Copy the code
  1. If you specifyhandlerAnd from themhandlersIf the array length after deletion is 0, it is cleared

emit

  1. willhandlersAll of thehandlerIf marked only once, it is removed from the array when it is finished
for ( let handler of handlers ) { handler.apply( this, args ); if(handler._once_){ onceHandled.push(handler); }}Copy the code
  1. If there is no correspondingtypeWould go,type*Downgrading scheme of

Why use DELETE rather than delete directly?

! [] // false ! undefined // trueCopy the code

If only a one-time type is cleared, it will be unable to go to the degrade scheme if the type is sent multiple times.

How to match?

So if you say is there a handler in the Handlers?

Due to the incomplete understanding of JS closures and other knowledge, I will skip it temporarily.

pending

Rewrite using swift.

Officially provided Event Bus

registered

Mount a variable above the Vue prototype in main.js

Vue.prototype.Event = new Vue()
Copy the code

The subscriber

When subscribing, be careful to release in time, otherwise it may be executed multiple times

// mounted or any other time
this.Event.$on('xxx'.() = > {})
// onDestroyed or other timing
this.Event.$off('xxx')
Copy the code

The publisher

this.Event.$emit('xxx'.() = > {})
Copy the code

The basic use

The installation

npm i --save event-pubsub
Copy the code

Node

Detailed use of visible official documentation.

var events = new window.EventPubSub();

events.on(
    'hello'.function(data){
        console.log('hello event recieved ', data);
        events.emit(
            'world',
            {
                type:'myObject'.data: {x:'YAY, Objects! '}})}); events.emit('hello'.'world'
 );

 events.emit(
     'hello'.'again'.'and again'
 );
Copy the code

The source code

'use strict'; window.EventPubSub=class EventPubSub { constructor( scope ) { this._events_ = {}; this.publish = this.trigger = this.emit; this.subscribe = this.on; this.unSubscribe = this.off; } on( type, handler, once ) { if ( ! handler ) { throw new ReferenceError( 'handler not defined.' ); } if ( ! this._events_[ type ] ) { this._events_[ type ] = []; } if(once){ handler._once_ = once; } this._events_[ type ].push( handler ); return this; } once( type, handler ) { return this.on( type, handler, true ); } off( type, handler ) { if ( ! this._events_[ type ] ) { return this; } if ( ! handler ) { throw new ReferenceError( 'handler not defined. if you wish to remove all handlers from the event please pass "*" as the handler' ); } if ( handler == '*' ) { delete this._events_[ type ]; return this; } const handlers = this._events_[ type ]; while ( handlers.includes( handler ) ) { handlers.splice( handlers.indexOf( handler ), 1 ); } if ( handlers.length < 1 ) { delete this._events_[ type ]; } return this; } emit( type, ... args ) { if ( ! this._events_[ type ] ) { return this.emit$( type, ... args ); } const handlers = this._events_[ type ]; const onceHandled=[]; for ( let handler of handlers ) { handler.apply( this, args ); if(handler._once_){ onceHandled.push(handler); } } for(let handler of onceHandled){ this.off(type,handler); } return this.emit$( type, ... args ); } emit$( type, ... args ) { if ( ! this._events_[ '*' ] ) { return this; } const catchAll = this._events_[ '*' ]; for ( let handler of catchAll ) { handler.call( this, type, ... args ); } return this; } } if (! Array.prototype.includes) { Array.prototype.includes = function(searchElement /*, fromIndex*/) { 'use strict'; if (this == null) { throw new TypeError('Array.prototype.includes called on null or undefined'); } var O = Object(this); var len = parseInt(O.length, 10) || 0; if (len === 0) { return false; } var n = parseInt(arguments[1], 10) || 0; var k; if (n >= 0) { k = n; } else { k = len + n; if (k < 0) {k = 0; } } var currentElement; while (k < len) { currentElement = O[k]; if (searchElement === currentElement || (searchElement ! == searchElement && currentElement ! == currentElement)) { // NaN ! == NaN return true; } k++; } return false; }; }Copy the code