浏览器端的EventEmitter

  1 <!DOCTYPE html>
  2 <html lang="en">
  3 
  4 <head>
  5     <meta charset="UTF-8">
  6     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  8     <title>Document</title>
  9 </head>
 10 
 11 <body>
 12     <script>
 13         // 浏览器端的EventEmitter
 14         /**
 15          * 采用的发布订阅模式-和vue中的eventBus类似
 16          * 将eventBus作为组件传递数据的桥梁,所有组件公用相同的事件中心,可以向该中心注册发送事件或接收事件,
 17          * 所有组件都可以收到通知,使用起来非常便利,其核心就是发布-订阅模式的落地实现
 18         */
 19         function EventEmitter(params) {
 20             this.__events = {}
 21         }
 22         EventEmitter.VERSION = '1.0.0'
 23         // 实现on方法
 24         EventEmitter.prototype.on = function (eventName, listener) {
 25             if (!eventName || !listener) return
 26             if (!isValidListener(listener)) {
 27                 throw new TypeError('listener must be a function')
 28 
 29             }
 30             var events = this.__events
 31             var listeners = events[eventName] = events[eventName] || []
 32             var listenerIsWrapped = typeof listener === 'object';
 33             // 不添加重复事件,判断是否有一样的
 34             if (indexOf(listeners, listener) === -1) {
 35                 listeners.push(listenerIsWrapped ? listener : {
 36                     listener: listener,
 37                     once: false
 38                 })
 39             }
 40             return this
 41         }
 42         // 判断
 43         function isValidListener(listener) {
 44             if (typeof listener === 'function') {
 45                 return true
 46             } else if (listener && typeof listener === 'object') {
 47                 return isValidListener(listener.listener)
 48             } else {
 49                 return false
 50             }
 51 
 52         }
 53         // 判断新增自定义事件是否存在
 54         function indexOf(array, item) {
 55             var result = -1;
 56             item = typeof item === "object" ? item.listener : item
 57             for (let i = 0; i < array.length; i++) {
 58                 const element = array[i].listener;
 59                 if (element === item) {
 60                     result = i
 61                     break
 62                 }
 63 
 64             }
 65             return result
 66 
 67         }
 68 
 69         EventEmitter.prototype.emit = function (eventName, args) {
 70             // 直接通过内部对象获取自定义事件的回调函数
 71             var listener = this.__events[eventName]
 72             if (!listeners) return
 73             for (let i = 0; i < listeners.length; i++) {
 74                 const element = listeners[i];
 75                 if (listener) {
 76                     listener.listener.apply(this, args || [])
 77                     // 给listener中的once为true的进行特殊处理
 78                     if (listener.once) {
 79                         this.off(eventName, listener.listener)
 80                     }
 81                 }
 82 
 83             }
 84             return this
 85         }
 86         EventEmitter.prototype.off = function (eventName, args) {
 87             var listeners = this.__events[eventName]
 88             if (!listeners) {
 89                 return
 90             }
 91             var index;
 92             for (var i = 0, len = listeners.length; i < len; i++) {
 93                if (listeners[i]&&listeners[i].listener===listener) {
 94                    index=i
 95                    break
 96                }
 97 
 98             }
 99             if (typeof index!=='undefined') {
100                 listeners.splice(index,1,null)
101             }
102             return this
103         }
104         EventEmitter.prototype.once = function (eventName, listener) {
105             // 直接调用on方法,once参数传入true,待执行之后进行once处理
106             return this.on(eventName,{
107                 listener:listener,
108                 once
109             })
110         }
111         EventEmitter.prototype.allOff = function (eventName) {
112             // 如果该eventName存在,则将其对应的listeners的数组直接清空
113             if (eventName&&this.__events[eventName]) {
114                 this.__events[eventName]=[]
115             }else{
116                 this.__events={}
117             }
118         }
119 
120     </script>
121 </body>
122 
123 </html>

 

posted @ 2022-11-26 19:01  古德拉克  阅读(111)  评论(0编辑  收藏  举报