发布订阅者模式以及vue中数据劫持 +结合发布/订阅模式

1,188 阅读1分钟

class Event {
	constructor(){
		this.events = {}
	}
	on(type, handler) {
		if(!this.events.hasOwnProperty(type)){
			this.events[type] = [];
		}
		this.events[type].push(handler)
    	        return this;
  	}
  	emit(type, ...args) {
	    for(let i = 0; i < this.events[type].length; i++) {
	       this.events[type][i].apply(this, args)
	    }
    	    return this;
  	}
  	off(type, handler){
  		if(!this.events.hasOwnProperty(type)){
  			throw new Error(`不存在${type}`)
  		}
  		const len = this.events[type].length
  		const eventHandler = this.events[type]
  		for(let i = 0; i < len; i++) {
  			if(eventHandler[i] == handler){
  				eventHandler.splice(i, 1)
  			}
  		}
  		return this;
  	}
  	once(type, handler){
		const on = (...args)  => {
		  handler.apply(this, args)
	      this.off(type, on)
	    }
	    this.on(type, on)
    	    return this;
  	}
}

const event = new Event()
const a1 = function(data){
    console.log(1 + data);
}
// event.on('a', a1);
// event.emit('a', '我是第1次调用的参数');
// event.emit('a', '我是第2次调用的参数');  
event.once('b', a1);
event.emit('b', '一次');
event.emit('b', '两次');



// vue中数据劫持结合发布/订阅模式
class Observer {
	constructor (value) {
	    this.value = value
	    this.dep = new Dep()
	    this.walk(value)
  	}
  	walk (obj) {
	    const keys = Object.keys(obj)
	    for (let i = 0; i < keys.length; i++) {
	      defineReactive(obj, keys[i],obj[keys[i]])
	    }
  	}
}


function defineReactive (obj, key, value){
    const dep = new Dep()

    Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter () {
    	console.log('get')
        dep.addSub({
        	update:()=>{
        		console.log('执行update')
        	}
        });
        return value
    },
    set: function reactiveSetter (newVal) {
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return
      }
      console.log('set')
	  value = newVal;
	  dep.notify();
    }
  })

}


class Dep {
	constructor (valuey) {
     	this.subs = [];
	}
	addSub(sub){
         this.subs.push(sub);
    }
    notify(){
	     this.subs.forEach(function(sub){
	         sub.update();
	     });
    }
}
let obj ={a:1,b:2,c:3}

new Observer(obj)
obj.a
obj.a = 2

对发布订阅者的通俗理解

订阅可以理解为寄存,发布理解为寄存的拿出调用,可以寄存很多个,拿出很多个

观察者模式主要是监听