创建和监听自定义事件

做前端开发的筒子们,有没有经常觉得原生的事件类型不够用?今天就来介绍一下如何创建自定义的事件类型吧。

举个例子,你有没有实现过像“长按”这样的需求?这是一个挺常见的需求,可是原生的事件类型里并没有它。以前通常的做法是用 mousedown 和 mouseup 来模拟。同时监听这两个事件,记录两次事件触发的时间戳,得出按下时长,再决定是否执行后续动作。这个方案还不错,思路清晰,实现容易。

好,现在新的需求来了(该死的 PM!),页面上有两个需要监听长按状态的元素,怎么办?这好办,写具名函数嘛,复用一下还是很容易的。别急,PM 又来了…… 两个元素触发长按所需的时长不一样,怎么办?时长还要能方便的修改,怎么办?在心里咒骂 PM 肯定少不了,但需求还是得给他实现了。好,修修改改勉强又能用了。可是这么一看,代码写得真丑啊…… 万一待会 PM 又改需求怎么办?

有没有办法把这个需求实现得简单好看又灵活呢?当然可以!创建一个自定义事件吧骚年!

在文档对象模型(DOM)中有 createEvent,initEvent,dispatchEvent 这么一组方法可以很方便的创建,初始化和触发一个自定义的事件。以前面提到的长按需求为例,我们首先需要创建一个事件对象。

 
 
  1. var evt = document.createEvent('Event');

在这里我基于最基础的事件模块(Event)创建了一个对象,如果你需要对事件进行精细地控制,可以选择更具体的事件模块(UIEvents、MouseEvents、MutationEvents、HTMLEvents 等)。

接下来就是初始化这个事件,三个参数分别是事件类型(字符串)、是否冒泡(布尔)、是否可取消(布尔)。

 
 
  1. evt.initEvent('longpress', true, true);

注意这里初始化事件的方法名跟上一步所选的事件模块是有关的,具体可以参照 MDN 这个表格

然后我们要做的事,就是在特定条件(按下时间超过 1 秒)下触发这个事件。

 
 
  1. var timer;
  2. button.addEventListener('mousedown', function() {
  3. timer = Date.now();
  4. }, false);
  5. button.addEventListener('mouseup', function() {
  6. if(Date.now() - timer > 1000) {
  7. evt.duration = Date.now() - timer;
  8. button.dispatchEvent(evt);
  9. }
  10. }, false);

检测鼠标按下和松开之间的时间间隔,大于 1 秒(1000 毫秒)则触发自定义的 longpress 事件。在这个过程中我们还可以为自定义的事件对象增加属性,比如上面例子中的 duration 属性,即鼠标按下的时长。

最后只需要像监听原生的事件那样,监听这个自定义的事件,太简单了。

 
 
  1. button.addEventListener('longpress', function(e) {
  2. console.log('Pressed for ' + e.duration + ' milliseconds.');
  3. }, false);

到这里就结束了吗?当然没有,别忘了 PM 的需求,触发事件的时长要可以方便的修改,还要能支持多个实例。

不过我想你应该也知道要怎么做了,就是把自定义事件的这部分代码包装一下。

 
 
  1. function enableLongPress(target, threshold) {
  2. var timer;
  3. var evt = document.createEvent('Event');
  4. evt.initEvent('longpress', true, true);
  5. target.addEventListener('mousedown', function() {
  6. timer = Date.now();
  7. }, false);
  8. target.addEventListener('mouseup', function() {
  9. if(Date.now() - timer > threshold) {
  10. evt.duration = Date.now() - timer;
  11. target.dispatchEvent(evt);
  12. }
  13. }, false);
  14. }

把需要监听的 DOM 元素和触发事件的条件作为参数传入,调用这个函数,就完成了事件的自定义。

 
 
  1. enableLongPress(button, 1000);

事件的监听部分完全不用改动。

 
 
  1. button.addEventListener('longpress', function(e) {
  2. console.log('Pressed for ' + e.duration + ' milliseconds.');
  3. }, false);

增加实例易如反掌。

 
 
  1. enableLongPress(anotherButton, 2000);
  2. anotherButton.addEventListener('longpress', function(e) {
  3. console.log('Pressed for ' + e.duration + ' milliseconds.');
  4. }, false);
var cfg = { serviceUrl: { teamProfile: 'http://api.sportsdatallc.org/nba-t3/teams/583ec773-fb46-11e1-82cb-f4ce4684ea4c/profile.json?api_key=p9sb9y9cha7wku5vyd55ytwh', standing: 'http://api.sportsdatallc.org/nba-t3/seasontd/2014/reg/standings.json?api_key=p9sb9y9cha7wku5vyd55ytwh', }, };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值