精华内容
下载资源
问答
  • 手写发布订阅模式 EventEmitter

    千次阅读 2019-10-22 16:28:40
    手写发布订阅模式 EventEmitter 1.简介 最近发现好多大厂面试题里都有手写发布订阅模式 EventEmitter,原因是 vue 和 react 的非父子组件的通信就是靠他实现的,下面是一个简易版的 EventEmitter。 2.代码 // 发布...

    手写发布订阅模式 EventEmitter

    1.简介

    最近发现好多大厂面试题里都有手写发布订阅模式 EventEmitter,原因是 vue 和 react 的非父子组件的通信就是靠他实现的,下面是一个简易版的 EventEmitter。

    2.代码

    // 发布订阅模式
    class EventEmitter {
      constructor() {
        // 事件对象,存放订阅的名字和事件  如:  { click: [ handle1, handle2 ]  }
        this.events = {}
      }
      // 订阅事件的方法
      on(eventName, callback) {
        if (!this.events[eventName]) {
          // 一个名字可以订阅多个事件函数
          this.events[eventName] = [callback]
        } else {
          // 存在则push到指定数组的尾部保存
          this.events[eventName].push(callback)
        }
      }
      // 触发事件的方法
      emit(eventName, ...rest) {
        // 遍历执行所有订阅的事件
        this.events[eventName] &&
          this.events[eventName].forEach(f => f.apply(this, rest))
      }
      // 移除订阅事件
      remove(eventName, callback) {
        if (this.events[eventName]) {
          this.events[eventName] = this.events[eventName].filter(f => f != callback)
        }
      }
      // 只执行一次订阅的事件,然后移除
       once(eventName, callback) {
        // 绑定的时fn, 执行的时候会触发fn函数
        const fn = (...rest) => {
          callback.apply(this, rest) // fn函数中调用原有的callback
          this.remove(eventName, fn) // 删除fn, 再次执行的时候之后执行一次
        }
        this.on(eventName, fn)
      }
    }
    

    3.使用

    const event = new EventEmitter()
    
    const handle = (...pyload) => console.log(pyload)
    
    event.on('click', handle)
    
    event.emit('click', 100, 200, 300, 100)
    
    event.remove('click', handle)
    
    event.once('dbclick', function() {
      console.log('click')
    })
    
    event.emit('dbclick', 100)
    
    
    

    参考链接

    1.https://www.fed123.com/javascriptnodejs/4681.html

    2.https://www.jianshu.com/p/e0575e17de2a

    展开全文
  • JS手写发布订阅

    2021-02-17 18:53:05
    手写发布订阅 class pubSub { constructor(){ this.list = {} } // 订阅 subscribe(key, fn) { if (!this.list[key]) { this.list[key] = [] } this.list[key].push(fn) } // 发布 publish(key, ......

    手写发布订阅

    class pubSub {
        constructor(){
            this.list = {}
        }
        // 订阅
        subscribe(key, fn) {  
            if (!this.list[key]) {
                this.list[key] = []
            }
            this.list[key].push(fn)
        }
        // 发布
        publish(key, ...args) {  
            for (let fn of this.list[key]) {
                fn.apply(this, args)
            }
        }
        // 取消订阅
        unSubscribe(key, fn) { 
            let fnlist = this.list[key]
            if (!fnlist) return
            if (!fn) {
                fnlist.length = 0
            } else {
                fnlist.forEach((item, index) => {
                    if (item === index) {
                        fnlist.splice(index, 1)
                    }
                })
            }
        }
    }
    
    let p1 = new pubSub()
    p1.subscribe('onwork', (time) => { console.log("上班了:" + time) })
    p1.subscribe('offwork', (time) => { console.log("下班了:" + time) })
    p1.subscribe('launch', (time) => { console.log("吃饭了:" + time) })
    
    // 发布
    p1.publish('onwork', '9:00:00')      // 上班了:9:00:00
    p1.publish('offwork', '18:00:00')    // 下班了:18:00:00
    p1.publish('launch', '12:00:00')     // 吃饭了:12:00:00
    
    p1.unSubscribe('onwork')
    p1.publish('onwork', '1222:00:00')
    
    展开全文
  • 上次研究观察者模式,很多文章说它也叫Subscribe/Publish(发布/订阅模式)。可在《Javascript设计模式》一书中,这两种模式还是有些区别的。书中原话如下: 1.Observer模式要求希望接收到主题通知者的观察者必须订阅...
  • 我们先写一个简单的发布订阅: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" c...
    在这里插入图片描述

    我们先写一个简单的发布订阅:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>发布订阅模式</title>
    </head>
    <body>
    	<script type="text/javascript">
    		var shopObj = {} // 定义发布者 卖家对象
    		shopObj.list = [] // 缓存列表 存放订阅函数
    
    	<span class="token comment">// 添加订阅者</span>
    	shopObj<span class="token punctuation">.</span><span class="token function-variable function">listen</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		shopObj<span class="token punctuation">.</span>list<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span>
    	<span class="token punctuation">}</span>
    
    	<span class="token comment">// 发布消息</span>
    	shopObj<span class="token punctuation">.</span><span class="token function-variable function">trigger</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> fn<span class="token punctuation">;</span> fn <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>list<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    			<span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span>
    		<span class="token punctuation">}</span>
    	<span class="token punctuation">}</span>
    
    	<span class="token comment">// 添加第一个订阅者</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">color<span class="token punctuation">,</span> size</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">订阅者1:颜色是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, 尺码是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    	<span class="token punctuation">}</span><span class="token punctuation">)</span>
    
    	<span class="token comment">// 添加第二个订阅者</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">color<span class="token punctuation">,</span> size</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">订阅者2:颜色是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, again尺码是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    	<span class="token punctuation">}</span><span class="token punctuation">)</span>
    
    	<span class="token comment">// 发布第一个消息 本意是要通知第1个订阅者 橘黄色 42尺码的货到了</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">'orange'</span><span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span>
    	<span class="token comment">// 发布第二个消息 本意是要通知第2个订阅者 黑色 39尺码的货到了</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">'black'</span><span class="token punctuation">,</span> <span class="token number">39</span><span class="token punctuation">)</span>
    
    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    

    </body>
    </html>

    在这里插入图片描述

    可以看到,已经可以订阅消息,并且发布消息,但是有个问题,就是发布消息的时候,把消息发送给所有订阅者了,怎么才能解决这个问题呢?

    我们回忆一下,我们在使用发布订阅的时候,是不是这样使用的,要传入一个标识:
    在这里插入图片描述
    然后在触发时候,和订阅时候传入的标识对应上,是不是就能解决这个问题了

    我们这样改造: 添加订阅时候,传入一个标识符key, 如果缓存列表里不存在对应的list[key],那么就创建一个对应的list[key]初始值是一个空数组[]

    如果有的话,直接把回调函数push进入对应的list[key]
    在这里插入图片描述
    完整代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<meta name="viewport" content="width=device-width, initial-scale=1.0">
    	<title>发布订阅模式2-优化</title>
    </head>
    <body>
    	<script type="text/javascript">
    		var shopObj = {} // 定义发布者 卖家对象
    		shopObj.list = [] // 缓存列表 存放订阅函数
    
    	<span class="token comment">// 添加订阅者</span>
    	shopObj<span class="token punctuation">.</span><span class="token function-variable function">listen</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		<span class="token comment">// 没有对应key的话就创建一个数组</span>
    		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>list<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    			<span class="token keyword">this</span><span class="token punctuation">.</span>list<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    		<span class="token punctuation">}</span>
    		<span class="token comment">// 然后再把回调函数push进list[key]</span>
    		shopObj<span class="token punctuation">.</span>list<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>fn<span class="token punctuation">)</span>
    	<span class="token punctuation">}</span>
    
    	<span class="token comment">// 发布消息</span>
    	shopObj<span class="token punctuation">.</span><span class="token function-variable function">trigger</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		<span class="token comment">// 获取对应的key</span>
    		<span class="token keyword">var</span> key <span class="token operator">=</span> <span class="token class-name">Array</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>arguments<span class="token punctuation">)</span> <span class="token comment">// 这里因为arguments是一个类数组 没有shift方法 需要借用</span>
    		<span class="token keyword">var</span> fns <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>list<span class="token punctuation">[</span>key<span class="token punctuation">]</span>
    		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fns <span class="token operator">||</span> fns<span class="token punctuation">.</span>length <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    			<span class="token keyword">return</span>
    		<span class="token punctuation">}</span>
    
    		<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i<span class="token operator">=</span><span class="token number">0</span><span class="token punctuation">,</span> fn<span class="token punctuation">;</span> fn <span class="token operator">=</span> fns<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    			<span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span>
    		<span class="token punctuation">}</span>
    	<span class="token punctuation">}</span>
    
    	<span class="token comment">// 添加第一个订阅者dean</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'dean'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">color<span class="token punctuation">,</span> size</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">订阅者dean:颜色是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, 尺码是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">的鞋子到货了!</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    	<span class="token punctuation">}</span><span class="token punctuation">)</span>
    
    	<span class="token comment">// 添加第二个订阅者jing</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token string">'jing'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">color<span class="token punctuation">,</span> size</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
    		console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">订阅者jing:颜色是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>color<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">, again尺码是</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${<!-- --></span>size<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">的鞋子到货了!</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
    	<span class="token punctuation">}</span><span class="token punctuation">)</span>
    
    	<span class="token comment">// 发布第一个消息 通知第dean 橘黄色 42尺码的鞋子到货了</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">'dean'</span><span class="token punctuation">,</span> <span class="token string">'orange'</span><span class="token punctuation">,</span> <span class="token number">42</span><span class="token punctuation">)</span>
    
    
    	<span class="token comment">// 发布第二个消息 通知第jing 黑色 39尺码的货到了</span>
    	shopObj<span class="token punctuation">.</span><span class="token function">trigger</span><span class="token punctuation">(</span><span class="token string">'jing'</span><span class="token punctuation">,</span> <span class="token string">'black'</span><span class="token punctuation">,</span> <span class="token number">39</span><span class="token punctuation">)</span>
    
    </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
    

    </body>
    </html>

    /pre>

    在这里插入图片描述

    我们优化一下代码,再添加一个取消订阅:

    var event = {
      list: [],
      listen: function(key, fn) {
        // 没有对应key的话就创建一个数组
        if (!this.list[key]) {
          this.list[key] = []
        }
        // 然后再把回调函数push进list[key]
        shopObj.list[key].push(fn)
      },
      trigger: function() {
        // 获取对应的key
        var key = Array.prototype.shift.call(arguments)
        var fns = this.list[key]
        if (!fns || fns.length === 0) {
          return
        }
    
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> fn<span class="token punctuation">;</span> fn <span class="token operator">=</span> fns<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
      <span class="token function">fn</span><span class="token punctuation">(</span><span class="token operator">...</span>arguments<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    

    },
    // 取消订阅
    remove: function(key, fn) {
    var fns = this.list[key]
    if (!fns) {
    return false
    } else {
    for (var i = fns.length - 1; i >= 0; i) {
    var _fn = fns[i]
    if (_fn == fn) {
    fns.splice(i, 1)
    }
    }
    }
    }
    }

    代码还可以用立即执行函数封装一下:

    // 代码封装成立即执行函数
    var Event = (function() {
      var list = [],
        listen,
        trigger,
        remove;
      listen = function(key, fn) {
          // 没有对应key的话就创建一个数组
          if (!this.list[key]) {
            this.list[key] = []
          }
          // 然后再把回调函数push进list[key]
          shopObj.list[key].push(fn)
        },
        trigger = function() {
          // 获取对应的key
          var key = Array.prototype.shift.call(arguments)
          var fns = this.list[key]
          if (!fns || fns.length === 0) {
            return
          }
    
      <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> fn<span class="token punctuation">;</span> fn <span class="token operator">=</span> fns<span class="token punctuation">[</span>i<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">;</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token function">fn</span><span class="token punctuation">(</span><span class="token operator">...</span>arguments<span class="token punctuation">)</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function-variable function">remove</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">key<span class="token punctuation">,</span> fn</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
      <span class="token keyword">var</span> fns <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>list<span class="token punctuation">[</span>key<span class="token punctuation">]</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>fns<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> fns<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">&gt;=</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">--</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
          <span class="token keyword">var</span> _fn <span class="token operator">=</span> fns<span class="token punctuation">[</span>i<span class="token punctuation">]</span>
          <span class="token keyword">if</span> <span class="token punctuation">(</span>_fn <span class="token operator">==</span> fn<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
            fns<span class="token punctuation">.</span><span class="token function">splice</span><span class="token punctuation">(</span>i<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    

    return {
    listen,
    trigger,
    remove
    }
    })()

    我们再看一下,发布订阅模式的使用场景: 解决异步调用中的强耦合问题:

    在这里插入图片描述
    在这里插入图片描述

    这种强耦合代码,缺点是,修改一个地方,其他地方都要跟着一起修改

    使用发布订阅模式修改:
    在这里插入图片描述
    在这里插入图片描述

    我们接着在vue里面自己手写一个简易的发布订阅模块:

    Main.vue

    <template>
      <div>
        <el-input type="text" v-model="name" placeholder="Input name"></el-input>
        <el-button type="primary" @click="handlePub">Pub</el-button>
        <Son />
      </div>
    </template>
    

    <script>
    import Son from ‘./Son.vue’
    import pubsub from ‘./utils/pubsub2’
    export default {
    name: ‘Pub’,
    components: {
    Son
    },
    data () {
    return {
    name: ‘’
    }
    },
    methods: {
    handlePub () {
    pubsub.trigger(‘item’, this.name)
    }
    }
    }
    </script>

    <style>

    </style>

    Son.vue

    <template>
      <div>
        <h1>{{content}}</h1>
      </div>
    </template>
    

    <script>
    import pubsub from ‘./utils/pubsub2’
    export default {
    name: ‘Son’,
    data () {
    return {
    content: ‘’
    }
    },
    mounted () {
    let _this = this // 这里要注意this指向 或者用箭头函数
    pubsub.listen(‘item’, function(data) {
    console.log(‘data:’, data)
    console.log(‘this:’,this)
    _this.content = data
    })
    }
    }
    </script>

    <style>

    </style>

    pubsub2.js

    var Event = (function(){
      var list = [],
      listen,
      trigger,
      remove;
      listen = function (key, fn) {
        // 没有对应key的话就创建一个数组
        if (!list[key]) {
          list[key] = []
        }
        // 然后再把回调函数push进list[key]
        list[key].push(fn)
      },
      trigger = function () {
        // 获取对应的key
        var key = Array.prototype.shift.call(arguments)
        var fns = list[key]
        if (!fns || fns.length === 0) {
          return
        }
    
    <span class="token comment">// for (var i=0, fn; fn = fns[i++];) {<!-- --></span>
    <span class="token comment">//   fn(...arguments)</span>
    <span class="token comment">// }</span>
    
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">&lt;</span> fns<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
      <span class="token keyword">var</span> fn <span class="token operator">=</span> fns<span class="token punctuation">[</span>i<span class="token punctuation">]</span>
      <span class="token function">fn</span><span class="token punctuation">(</span><span class="token operator">...</span>arguments<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    

    },
    remove = function (key, fn) {
    var fns = list[key]
    if (!fns) {
    return false
    } else {
    for (var i = fns.length - 1; i >= 0; i) {
    var _fn = fns[i]
    if (_fn == fn) {
    fns.splice(i, 1)
    }
    }
    }
    }
    return {
    listen,
    trigger,
    remove
    }
    })()

    export default Event

    在这里插入图片描述
    效果:
    在这里插入图片描述

    转载:https://blog.csdn.net/dyw3390199/article/details/118651237?utm_medium=distribute.pc_feed_v2.none-task-blog-personrec_tag-6.pc_personrecdepth_1-utm_source=distribute.pc_feed_v2.none-task-blog-personrec_tag-6.pc_personrec
    展开全文
  • js代码-发布订阅模式 JavaScript 发布-订阅模式 - 掘金 https://juejin.im/post/6844903850105634824
  • JS简单实现发布订阅模式

    千次阅读 2021-01-30 17:36:52
    发布订阅模式发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。 那他们之间如何交流? 由一个调度中心来做中间人,发布者更新(publish)主题,由主题(调度中心)来进行通知...

    在这里插入图片描述

    发布订阅模式

    在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。

    那他们之间如何交流?

    由一个调度中心来做中间人,发布者更新(publish)主题,由主题(调度中心)来进行通知(noticy)订阅者更新(update)。
    在这里插入图片描述

    简单的代码实现

    参考网上class面向对象实现,相较于很多js event的实现便于理解

    // 主题
    class Dep {
      constructor(callback) {
        this.subs = []; // 主题的订阅者
        this.callback = callback;
      }
    
      // 添加订阅者
      addSub(sub) {
        this.subs.push(sub);
        return this;
      }
    
      // 主题更新通知---调用订阅者update,通知所有订阅者
      notify() {
        this.subs.forEach(item => item.update(this.callback));
      }
    }
    
    // 订阅者
    class Sub {
      constructor(val) {
        this.val = val;
      }
    
      update(callback) {
        this.val = callback(this.val); // 执行订阅主题的函数
        console.log('更新之后:', this.val);
      }
    }
    
    // 发布者
    class Pub {
      constructor() {
        this.deps = []; // 发布的主题列表
      }
    
      // 添加主题
      addDep(dep) {
        this.deps.push(dep);
      }
    
      // 移除主题
      removeDep(dep) {
        let index = this.deps.indexOf(dep);
        if (index !== -1) {
          this.deps.splice(index, 1);
          return true;
        } else {
          return false;
        }
      }
    
      // 更新主题
      publish(dep) {
        this.deps.forEach(item => item == dep && item.notify());
      }
    }
    
    // 新建主题,给主题中加订阅者
    let dep1 = new Dep(item => item * item);
    dep1.addSub(new Sub(1)).addSub(new Sub(2)).addSub(new Sub(3));
    
    // 新建发布者
    let pub = new Pub();
    // 添加主题
    pub.addDep(dep1);
    
    // 发布者发布,通知这个主题的所有订阅者更新
    pub.publish(dep1);
    
    // 输出结果
    // 更新之后结果:1
    // 更新之后结果:4
    // 更新之后结果:9
    
    展开全文
  • 发布 订阅模式 // 事件触发器 class EventEmitter { constructor () { // { 'click': [fn1, fn2], 'change': [fn] } this.subs = Object.create(null) } // 注册事件 $on (eventType, handler) { ...
  • salesOffices.listen('squareMeter110', function(price) { // 小红订阅 110 平方米房子的消息 console.log('价格= ' + price); // 输出: 3000000 }); salesOffices.trigger('squareMeter88', 2000000); // 发布 ...
  • 发布订阅模式是什么 它其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。(如微信公众号一样有无数个订阅者,有一个发布者,当发布发布文章的时候,...
  • 最近空闲时间手撸代码实现了发布订阅模式,可以进行组件通信。 话不多说,直接上代码 /** * Created by laichengliang on 2021/04/13. */ const center = {} // 事件监听 center.on = (eventName, callback) ...
  • 发布订阅模式实现 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" ...
  • 一、什么是发布-订阅模式 我们在使用发布-订阅模式之前,先了解什么是发布-订阅模式。简单来说,发布订阅模式就是一种一对多的依赖关系。多个订阅者(一般是注册的函数)同时监听同一个数据对象,当这个...
  • 发布订阅模式 订阅: 由多个对象(用户)发起 发布: 在js中,可以这样做: 有一个对象,使用使用数组,把所有的对应函数,都先装起来 当需要的时候,把所有的函数都调用 <!DOCTYPE html> <...
  • 发布订阅 emit 执行该订阅下的所有函数 off 取消某个函数的订阅 once 只执行一次订阅事件 这里用Map 存储 EventBus 的数据(发布者-订阅者)。 ...
  • 经常会有面试题问发布订阅模式,很多童鞋都一脸懵逼,根本不知道在问什么,甚至觉得自己根本用不上这玩意。 其实,市面上的各大框架的事件处理,特别是组件通讯都基于发布订阅模式实现,比如vue的vuex,reace的...
  • 上周笔者的面试中,问到了很多设计模式相关的问题,而这部分知识已经学了很久了,于是决定开始拾起,先从一道高频的题目谈起设计模式:发布订阅模式 发布订阅模式是描述对象之间一对多的依赖关系的一种模式,可以...
  • 发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel)...
  • observer和subscribe/publish observer(观察者模式) 概念 ...目标状态发生改变并且观察者可能对这些改变感兴趣,就会发送一个通知消息...《JavaScript设计模式》一书中给出了观察者模式的实现方法,使用了四个组件(书
  • 里面还有还有顺带复习的其他知识点:for in和for of循环,普通对象可迭代。 上边是标准版,下边是自己写的简易版
  • 心血来潮,想要手写实现一个类似pubsub-js或者vue中央事件总线的发布订阅的小类库 代码如下: 新建一个文件 JasonMa_PubSub.js const JasonMa_PubSub = { //存储事件及方法 listenStore: {}, //订阅/监听 on: ...
  • 发布订阅模式能够广泛地应用于异步编程中,同时还可以让对象松耦合的联系在一起。这种设计模式也常见用于各大框架中,来简单看看然后自己写一个吧!!
  • on:订阅 emit:发布 off:取消 class EventHub { private cache: {[key: string]: Array<(data: unknown)=> void>} = {} on(eventName: string, fn: (data: unknown)=> void) { ...
  • 占坑
  • js代码-手写订阅模式
  • initial-scale=1.0"> 手写发布订阅title> head> <body> <div id="app"> <p v-text="name">p> <p v-text="age">p> <p v-text="name">p> div> <script> let data = { name: '区泽熙', age: 22, height: 176 } // 遍历...
  • 简介: 观察者模式或者说订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。 通俗来说,就像订报纸一样,只要你订阅了...
  • 手写订阅发布模式

    千次阅读 2018-06-03 12:27:43
    前几天在网上查阅了一些资料,并且自己尝试着手写了一下订阅发布模式。其实可以发现订阅发布模式和自定义事件类似(但不同),原理是我们先定义一个事件类型并给一个callback,在后续执行这个callback。var Works = ...
  • 简单例子 var salesoffice = {}; //定义售楼处 salesoffice.clientList = []; //缓存列表,存放订阅者的回... salesoffice.listen = function (key,fn) { //增加订阅者 if(!this.clientList[key]){ this.cl...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,421
精华内容 968
关键字:

手写发布订阅模式js