vue2.x框架里面的事件总线eventBus的原理解析

vuejs2.x里面的事件总线大家因该都会用了

let eventBus = new new()

然后我们就就可以获取到实例上的 o n , on, on,emit,$off事件了,从而就可以进行组件特别是兄弟组件之间的数据传递了!今天我们不讲怎么使用这个,主要记录下怎么实现这个总线的原理!不多说,上代码

发布—订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状
态发生改变时,所有依赖于它的对象都将得到通知。在 JavaScript 开发中,我们一般用事件模型
来替代传统的发布—订阅模式。

var salesOffices = {} //发布对象

salesOffices.clinetLists = []

//订阅事件
salesOffices.listen = function (fn) {
  this.clinetLists.push(fn)
}

//发布事件
salesOffices.trigger = function () {
  this.clinetLists.forEach((fn) => fn())
}

salesOffices.listen(function () {
  console.log('1')
})

salesOffices.listen(function () {
  console.log('2')
})

salesOffices.trigger()

上面的方法不能传递参数,我们再改进下

var salesOffices = {} //发布对象

salesOffices.clinetLists = []

//订阅事件
salesOffices.listen = function (fn) {
  this.clinetLists.push(fn)
}

//发布事件
salesOffices.trigger = function () {
  this.clinetLists.forEach((fn) => fn.apply(this, arguments)) //打印传进来的参数
}

salesOffices.listen(function (price, size) {
  console.log('1', price, size)
})

salesOffices.listen(function (price, size) {
  console.log('2', price, size)
})

salesOffices.trigger(30000, 200)
salesOffices.trigger(2000, 88)
var salesOffices = {} //发布对象
salesOffices.clinetLists = {} //缓存列表
//订阅事件
salesOffices.listen = function (key, fn) {
  if (!this.clinetLists[key]) {
    this.clinetLists[key] = [fn]
  }
  this.clinetLists[key].push(fn)
}

//发布事件
salesOffices.trigger = function () {
  var key = [].shift.call(arguments),
    fns = this.clinetLists[key]

  if (!fns || fns.length == 0) {
    return false
  }

  for (var i = 0, fn; (fn = fns[i++]); ) {
    fn.apply(null, arguments)
  }
}

//订阅消息
salesOffices.listen('squareMeter88', function (price, size) {
  // 小明订阅 88 平方米房子的消息
  console.log('价格= ' + price, '面积:' + size) // 输出: 2000000
})
salesOffices.listen('squareMeter100', function (price, size) {
  // 小红订阅 110 平方米房子的消息
  console.log('价格= ' + price, '面积:' + size) // 输出: 3000000
})

salesOffices.trigger('squareMeter88', 2000000, 88)
salesOffices.trigger('squareMeter100', 3000000, 100)

/* 自动注册发布订阅模式 */

var events = {
  clinetLists: {}, //必须味object
  listen: function (key, fn) {
    if (!this.clinetLists[key]) {
      this.clinetLists[key] = [fn]
    }
    this.clinetLists[key].push(fn)
  },
  trigger: function () {
    var key = [].shift.call(arguments),
      fns = this.clinetLists[key]
    if (!fns || fns.length == 0) {
      return false
    }
    for (var i = 0, fn; (fn = fns[i++]); ) {
      fn.apply(null, arguments)
    }
  }
}

上面还没有取消订阅的方法,我们再改进下

var events = {
  clinetLists: {}, //必须味object
  listen: function (key, fn) {
    if (!this.clinetLists[key]) {
      this.clinetLists[key] = [fn]
    }
    this.clinetLists[key].push(fn)
  },
  trigger: function () {
    var key = [].shift.call(arguments),
      fns = this.clinetLists[key]
    if (!fns || fns.length == 0) {
      return false
    }
    for (var i = 0, fn; (fn = fns[i++]); ) {
      fn.apply(null, arguments)
    }
  }
}

然后再测试下

var sales = {}

installEvent(sales)
let fn1, fn2
sales.listen(
  'squareMeter88',
  (fn1 = function (price) {
    // 小明订阅消息
    console.log('价格= ' + price)
  })
)
sales.listen(
  'squareMeter100',
  (fn2 = function (price) {
    // 小红订阅消息
    console.log('价格= ' + price)
  })
)

sales.trigger('squareMeter88', 2000) // 2000
sales.trigger('squareMeter100', 3000) // 3000

sales.remove('squareMeter88', fn1)
sales.trigger('squareMeter88', 2000) // 2000
sales.trigger('squareMeter100', 3000) // 3000

// 价格= 2000000 面积:88
// 价格= 3000000 面积:100
// 价格= 2000
// 价格= 3000
// 取消订阅成功fn1
// 价格= 3000

最终版的发布订阅模式

/* 全局的发布订阅模式 */

var Event = (function () {
  var clinetLists = {},
    on,
    emit,
    off,
    remove
  on = function (key, fn) {
    if (!clinetLists[key]) {
      clinetLists[key] = [fn]
    }
    clinetLists[key].push(fn)
  }
  emit = function () {
    var key = [].shift.call(arguments),
      fns = clinetLists[key]

    if (!fns && fns.length == 0) {
      return false
    }
    for (var i = 0, fn; (fn = fns[i++]); ) {
      fn.apply(null, arguments)
    }
  }
  remove = function (key, fn) {
    var fns = clinetLists[key]
    if (!fns) {
      return false
    }
    if (!fn) {
      fns && (fns.length = 0)
    } else {
      for (var l = fns.length - 1, _fn; (_fn = fns[l--]); ) {
        if (fn == _fn) {
          fns.splice(l, 1)
        }
      }
    }
  }
  return {
    on,
    emit,
    off
  }
})()

Event.on('test1', function (price) {
  // 小红订阅消息
  console.log('价格= ' + price) // 输出:'价格=2000000'
})
Event.on('test1', function (price) {
  // 小红订阅消息
  console.log('价格= ' + price) // 输出:'价格=2000000'
})
Event.on('test2', function (price) {
  // 小红订阅消息
  console.log('价格= ' + price) // 输出:'价格=2000000'
})

Event.emit('test2', 500)
Event.emit('test1', 500)

今天的总结就到此结束,有不足的地方可以提出大家互相学习~~~

你可能感兴趣的:(设计模式,vue2/vue3,javascript,前端,vue.js)