初面网初面网

发布-订阅模式

发布者和订阅者互不知晓对方存在,而由第三方实现调度。属于观察者模式的改良版。

  • 简单版
const PubSub = {
  list: [],
  publish(){
    this.list.forEach(item => item())
  },
  subscribe(cb){
    this.list.push(cb)
  }
}

function testA(){
  console.log("testA")
}
function testB(){
  console.log("testB")
}

PubSub.subscribe(testA)
PubSub.subscribe(testB)

PubSub.publish()
  • 进阶版
const PubSub = {
  message: {},
  publish(type, data){
    // this.list.forEach(item => item())
    if(!this.message[type])return
    this.message[type].forEach(item => item(data))
  },
  subscribe(type, cb){
    if(!this.message[type]){
      this.message[type] = [cb]
    }else{
      this.message[type].push(cb)
    }
  },
  unsubscribe(type, cb){
    if(!this.message[type]) return
    if(!cb){
      // 取消所有当前type事件
      this.message[type] && (this.message[type].length = 0)
    }else{
      this.message[type] = this.message[type].filter(item => item !== cb)
    }
  }
}

function testA(data){
  console.log("testA", data)
}
function testB(data){
  console.log("testB", data)
}
function testC(data){
  console.log("testC", data)
}

PubSub.subscribe("A", testA)
PubSub.subscribe("A", testC)
PubSub.subscribe("B", testB)

小例子

例子还是观察者的例子

/*
// body部分
<header class="header">
  路径
</header>

<div class="box">
  <div class="left">
    <ul>
      <li>首页</li>
      <li>用户管理</li>
      <li>权限管理</li>
      <li>新闻管理</li>
    </ul>
  </div>

  <div class="right">
    <div class="bread"></div>
  </div>
</div>
*/
const PubSub = {
  message: {},
  publish(type, data){
    // this.list.forEach(item => item())
    if(!this.message[type])return
    this.message[type].forEach(item => item(data))
  },
  subscribe(type, cb){
    if(!this.message[type]){
      this.message[type] = [cb]
    }else{
      this.message[type].push(cb)
    }
  },
  unsubscribe(type, cb){
    if(!this.message[type]) return
    if(!cb){
      // 取消所有当前type事件
      this.message[type] && (this.message[type].length = 0)
    }else{
      this.message[type] = this.message[type].filter(item => item !== cb)
    }
  }
}

PubSub.subscribe("UpdateBread", function(data){
  console.log("我是订阅者", data)
  document.querySelector(".bread").innerHTML = data
})

let oli = document.querySelectorAll(".left li")
for(let i = 0; i < oli.length; i++){
  oli[i].onclick = function(){
    PubSub.publish("UpdateBread", this.innerHTML)
  }
}

更新于 2025/2/26