简单实现一个事件模型

发布订阅模式

大家都知道,javascript本身就是事件驱动的语言,在日常的dom事件处理中,我们已经习惯了监听一个dom绑定一个事件,然后通过某些动作去触发这个事件,从而来达到想要的效果。事实上,我们非常熟悉这么一个模式,只不过可能不是很清楚这个模式的名字,其实这个模式就是发布订阅模式(又名观察者模式)

目标效果

我们想实现一个事件类,一共有三个方法:subscribe、unsubscribe、publish

subscribe方法用于订阅一个事件

unsubscribe方法用于取消一个已经订阅的事件

publish方法用于发布一个事件

实现思路

首先我们创建这么一个Event类,它有上面的那三个方法:

function Event() {
    this.subscribe = function() {}

    this.unsubscribe = function() {}

    this.publish = function() {}
}

然后我们需要一个对象,来对不同的事件和回调函数进行存储。我们可以把事件名作为这个对象里面的key, 事件的相关属性作为value;我们还需要一个id属性,给订阅的事件分配一个唯一的id,方便后续的一些操作:

function Event() {
    var map = {}
    var id = 0
    // ...
}

下面我们来实现这个subscribe方法。

在我们平时的dom操作中,订阅事件一般会接收两个参数:事件名和事件的处理回调,那么这里我们也接收这两个参数;然后我们的subscribe方法应该把传入的参数保存到我们的map对象中,进行存储。

// ...
this.subscribe = function(name, handler) {
    if(!map.hasOwnProperty(name) || !Array.isArray(map[name])) {
        map[name] = [];
    }
    var event = {
        id: id++,
        name: name,
        handler: handler
    }
    map[name].push(event)

    return event // 返回这个对象 方便那我们后续取消订阅
}
// ... 

接下来就是发布事件,我们传入事件名,然后publish方法将为我们执行对应的事件处理函数

this.publish = function() {
    var name = [].shift.call(arguments) // 传入的第一个参数为事件名 后续所有参数都将传入事件处理器中
    if(!map.hasOwnProperty(name) || !Array.isArray(map[name])) {
        console.log('event not found')
        return
    }
    for(var i = 0; i < map[name].length; i++) {
        var item = map[name][i]
        item.handler && item.handler.apply(null, arguments)
    }
}

现在我们可以测试一下这两个方法运行是不是正常:

var event = new Event();
event.subscribe('test_event', function(data) {
    console.log(data) // this is a text event info
})

event.publish('test_event', 'this is a text event info')

最后就是如何去取消我们的订阅了。在之前subscribe中,我们返回了一个对象,来表示绑定的事件,那么我们可以利用这个返回的对象,来取消这个订阅:

this.ubsubscribe = function(event) {
    if(!map.hasOwnProperty(event.name) ||  !Array.isArray(map[event.name])) {
        return
    }
    map[event.name] = map[event.name].filter(function(item) {
        return item.id !== event.id
    })
}

下面我测试一下这个方法:

var event = new Event();
var event1 = event.subscribe('test_event', function(data) {
    console.log('event1: ' + data)
})

var event2 = event.subscribe('test_event', function(data) {
    console.log('event2: ' + data)
})

event.publish('test_event', 'this is a text event info') 
// 打印两条数据
// event1: this is a text event info
// event2: this is a text event info

event.ubsubscribe(event1)

event.publish('test_event', 'this is a text event info')
// 只打印一条数据 说明我们的event1取消成功
// event2: this is a text event info

这样我们整个Event类就写完了~

结束

发布订阅模式是javascript事件的基础,是每个前端都应该了解的一种设计模式,这里我只是非常浅显简单的实现了一个发布订阅模式,希望对大家有所帮助~

原文地址:http://blog.yuantang.site/2017/08/19/简单实现一个事件模型

转载于:https://my.oschina.net/prettypice/blog/1517712

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值