观察者模式

观察者模式:一个对象一直在监视某种行为,一旦监视到这个行为发生了,就会去执行一个函数
其实事件绑定也是观察者模式

观察者模式与时间绑定的区别:

以前:绑定事件的事件源,必须是一个dom节点,事件类型必须是指定的
今天:绑定事件的事件源,可以是任意对象,事件类型可以是任意类型
 
class Watcher{
    constructor(){
        // 定义属性用来存储事件

        this.container = []
    }
    // 绑定事件
    addEventListener(type,handler){
        // 绑定的本质在做什么? - 将事件存储起来
        // var obj = {}
        // obj[type] = [handler] // 第一次将函数放在一个数组中

        // obj[type].push(handler) // 第二次将函数push到数组中
        // this.container.push(obj)

        // 遍历container,判断里面是否有type这个事件类型
        // 有就push,没有就创建数组,再push
        // var flag = true
        // var index;
        // for(var i=0;i<this.container.length;i++){
        //     if(type in this.container[i]){ // this.container[i]是一个对象
        //         // 判断一个键是否在对象中
        //         flag = false
        //         index = i
        //     }
        // }
        // // 通过flag判断事件类型是否在数组中
        // if(flag){
        //     var obj = {}
        //     obj[type] = [handler]
        //     this.container.push(obj)
        // }else{
        //     this.container[index][type].push(handler)
        // }

        var index = this.container.findIndex(v=>type in v)
        if(index===-1){
            var obj = {}
            obj[type] = [handler]
            this.container.push(obj)
        }else{
            this.container[index][type].push(handler)
        }

    }
    // 移除事件
    removeEventListener(type,handler){
        var index = this.container.findIndex(v=>type in v)
        if(index===-1){
            alert('事件还没绑定')
            return
        }
        // 要在arr中删除一个函数
        var arr = this.container[index][type]
        // this.container[index][type].splice(下标,1)
        // 在arr中找到handler的下标
        var i = arr.findIndex(v=>v===handler)
        arr.splice(i,1)
    }
    // 触发事件
    dispatchEvent(type,...arr){
        var e = {}
        e.type = type
        e.data = arr
        // 从container中找到对应的type,对应的函数组成的数组 - 遍历数组调用所有函数
        var index = this.container.findIndex(v=>type in v)
        if(index===-1){
            alert('事件还没有绑定不能触发')
            return
        }
        for(var i=0;i<this.container[index][type].length;i++){
            this.container[index][type][i](e)
        }
    }
}

var w = new Watcher()
function kan1(){
    console.log("第一次看见");
}
function kan2(){
    console.log("第二次看见");
}
function pao1(e){
    console.log(e); // 事件对象
    console.log("第一次跑");
}
// w.addEventListener('kan',kan1)
// w.addEventListener('kan',kan2)
w.addEventListener('pao',pao1)
// console.log(w);

// 解绑事件
// w.removeEventListener('kan',kan1)
// w.removeEventListener('aaa',kan1)

// 手动触发事件
// w.dispatchEvent('kan')
w.dispatchEvent('pao',1,2,3,4,5)

/*
选择使用什么样的数据取存储?
存多个值:数组、对象
对象键唯一,所以排除掉对象
数组:[
    事件1,{kan:[kan1,kan2]}
    事件2,{pao:[pao1]}
]
*/

// var index = arr.findIndex(v=>{
//     return type in v
// })

// console.dir(document);

// function fn(){
//     console.log("点击了文档");
// }
// document.addEventListener('click',fn)

// var e = new Event('click')
// // 手动触发事件
// document.dispatchEvent(e)

 

posted @ 2021-02-03 15:10  技术活当赏  阅读(67)  评论(0)    收藏  举报