概述
自定义事件很难派上用场?
为什么自定义事件很难派上用场,因为以前js不是模块化开发,也很少协作。因为事件本质是一种通信方式,是一种消息,只有存在多个对象,多个模块的情况下,才有可能需要用到事件进行通信。而现在有了模块化之后,已经可以使用自定义事件进行各模块间协作了。
哪里用得到自定义事件?
事件本质是一种消息,事件模式本质上是观察者模式的实现,那么用得上观察者模式的地方,自然也可以也可以用上事件模式。所以,如果:
1、一个目标对象改变,需要多个观察者调整自身的。
比如:我需要元素a点击之后,元素b显示鼠标的位置,元素c显示提示,元素d.....
2、分模块协作需要解耦的
比如:甲负责模块a,乙负责模块b,模块b需要a运行完之后才能运行
传统的写法将逻辑写在一个方法里面:
function dosomething(){ a(); b();}
这样做每次扩展都要修改a的点击函数,不好扩展。
自定义事件的写法
//1、创建事件var clickelem = new event(clickelem);//2、注册事件监听器elem.addeventlistener(clickelem,function(e){ //干点事})//3、触发事件elem.dispatchevent(clickelem);
可以看到,elem通过dispatchevent方法触发的事件,只有elem上注册的监听器才能监听得到。这就很没意思了,自己发给自己消息,通知自己去干什么。
创建自定义事件可参考: mdn : creating_and_triggering_events
应用
从前面 js 自定义事件 的描述中知道:元素a通过dispatchevent方法触发的事件,只有a上注册的监听器才能监听得到。
我们想要的效果是,别的对象干了某件事之后, 发个消息给我们,好让我们能做相应的改变。要做到这样,也不是没办法:我们可以在一个公共对象上监听和触发事件,这就很有意义了。
例子一:通知多个对象
要实现 元素a点击之后,元素b显示鼠标的位置,元素c显示提示,可以这样写:
文件:a.js
import b from ./bimport c from ./cvar a = document.getelementbyid(a);a.addeventlistener(click,function(e){ var clicka = new event(clicka); document.dispatchevent(clicka);});
注意:import进来的变量虽然不使用,但是一定不能省略
文件b.js:
var b = document.getelementbyid(b);document.addeventlistener(clicka,function(e){ b.innerhtml = (128,345);})
文件c.js:
var c = document.getelementbyid(c);document.addeventlistener(clicka,function(e){ c.innerhtml = 你点了a;})
这样写,三个模块之间完全不用关心对象,也不知道对方存在,耦合度非常的低,完全可以独立编写,不会互相影响。这其实就是一个观察者模式的实现。
例子二:游戏框架
要开发一个游戏,启动游戏,加载图片和音乐,加载完后,渲染场景和音效,加载和渲染由不同的人负责。可以这样写:
文件:index.js
import loadimage from ./loadimageimport loadmusic from ./loadmusicimport initscene from ./initscene var start = document.getelementbyid(start);start.addeventlistener(click,function(e){ console.log(游戏开始!); document.dispatchevent(new event(gamestart));})
文件:loadimage.js
// 加载图片document.addeventlistener(gamestart,function(){ console.log(加载图片...); settimeout(function(){ console.log(加载图片完成); document.dispatchevent(new event(loadimagesuccess)); },1000);});
文件:loadmusic.js
//加载音乐document.addeventlistener(gamestart,function(){ console.log(加载音乐...); settimeout(function(){ console.log(加载音乐完成); document.dispatchevent(new event(loadmusicsuccess)); },2000);});
文件:initscene.js
//渲染场景document.addeventlistener(loadimagesuccess,function(e){ console.log(使用图片创建场景...); settimeout(function(){ console.log(创建场景完成); },2000)});//渲染音效document.addeventlistener(loadmusicsuccess,function(e){ console.log(使用音乐创建音效...); settimeout(function(){ console.log(创建音效完成); },500)});
加载模块和渲染模块互不影响,易于扩展。
携带信息
除此之外,事件还能传递自定义信息:
var event = new customevent('myevent', { 'dataname': datacontent });document.dispatchevent(event);
(注意:传递自定义信息需要使用customevent,而不是event)
然后在监听函数里取出:
document.addeventlistener(myevent,function(e){ console.log(e.dataname);})
以上就是怎么用javascript实现自定义事件功能的详细内容。