在 JS 中,事件处理函数的绑定 addEventListener 就是发布订阅的模式。
addEventListener 由 EventTarget 对象提供。
方式
例子
var salesOffices = {}; // 售楼部salesOffices.clientList = []; // 花名册salesOffices.listen = function(fn) {this.clientList.push(fn);}salesOffices.trigger = function() {for(var i = 0; i < this.clientList.length; i++) {var fn = this.clientlist[i];fn.apply(this, arguments);}}salesOffices.listen(function(price, square) {console.log('zhangsan', price, square);});salesOffices.listen(function(price, square) {console.log('zhaosi', price, square);});setTimeout(() => {salesOffices.trigger(2000, 80);salesOffices.trigger(3000, 110);})
会出现一个问题,zhangsan 只关注价格 2000 以下的,zhaosi 只关注价格 3000 以上的。所以要增加一个标识来区分。
var salesOffices = {}; // 售楼部salesOffices.clientList = []; // 花名册salesOffices.listen = function(key, fn) {if(!this.clientList[key]) {this.clientList[key] = [];}this.clientList[key].push(fn);}salesOffices.trigger = function() {var key = Array.prototype.shift.call(arguments),fns = this.clientList[key];for(var i = 0; i < this.fns.length; i++) {var fn = this.clientlist[i];fn.apply(this, arguments);}}salesOffices.remove = function(key, fn) {var fns = this.clientList[key];if(!fns){return false;}for(var i = 0; i < fns.length; i++) {var _fn = fns[i];if(_fn === fn) {fns.splice(i, 1);}}}salesOffices.listen('2000meter', function(price, square) {console.log('zhangsan', price, square);});salesOffices.listen('3000meter', function(price, square) {console.log('zhaosi', price, square);});setTimeout(() => {salesOffices.trigger('2000meter', 2000, 80);salesOffices.trigger('3000meter', 3000, 110);})
实现
// 订阅者class Subscriber {constructor() {this.publishers = [];}// 订阅发布者subscribe(publisher) {this.publishers.push(publisher);}// 通知notify() {this.publishers.forEach(publisher => {publisher.update();})}}// 发布者class Publisher {constructor(callback) {this.callback = callback;}update() {this.callback();}}// 创建订阅者const sub = new Subscriber();// 创建发布者const publisher1 = new Publisher(() => console.log('Publisher1'));const publisher2 = new Publisher(() => console.log('Publisher2'));// 订阅发布者sub.subscribe(publisher1);sub.subscribe(publisher2);// 触发通知sub.notify();
