Event || 自定义事件
前言
所有以前不好好重视的基础,是现在要多花的时间,如果现在不好好补补,那未来就没机会花时间了。
这段时间对事件的监听有一个机会刚好可以大量的使用。或者说只有keydown事件吧。然后呢,通过学习优质的代码,感觉对event有了一个更深入的了解。特别是自定义事件的使用。
前置知识
在MDN上,创建一个event事件是这样的:
//以下兼容ES5
//创建一个事件build对象
var event = new Event('build');
// 挂在在elem上监听build事件,并且阻止冒泡
elem.addEventListener('build', function (e) { ... }, false);
// 然后触发这个事件
elem.dispatchEvent(event);
有时候在IE8以下是不兼容事件对象的:
// 创建一个事件对象
var event = document.createEvent('Event');
// 初始化事件对象的build事件
event.initEvent('build', true, true);
// 监听
document.addEventListener('build', function (e) {
// e.target matches document from above
}, false);
// 触发
document.dispatchEvent(event);
如果想进一步去设置事件的自定义属性:
var event = new CustomEvent('build', { 'detail': elem.dataset.time });
这些前置概念是不是看的有点蒙,看完之后感觉没什么卵用,毕竟触发事件还是要执行一段代码,难道还有手动去触发?没事我们来看一看demo。
实例讲解
为了体现为什么要自定义事件。我首先先写一个不用自定义事件的例子(我先贴代码后续改为网络连接到GitHub上):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>document 监听</title>
<style>
a {
text-align: center;
display: inline-block;
width: 20%;
height: 100px;
line-height: 100px;
font-size: 24px;
color: #000;
text-decoration: none;
margin: 10px;
background: #fff;
border: 1px solid #000;
}
//获取焦点的时候有白底黑字变成黑底白字
a:focus {
color: #fff;
background: #000;
outline: none;
}
</style>
</head>
<body>
<a href="javascript:;">1</a>
<a href="javascript:;">2</a>
<a href="javascript:;">3</a>
<a href="javascript:;">4</a>
<a href="javascript:;">5</a>
<script type="text/javascript">
var index = 0;
var a = document.querySelectorAll("a");
a[0].focus();
document.onkeydown = function(e) {
//按右键
if (e.keyCode === 39) {
// console.log(a.length)
index = index < a.length - 1 ? index + 1 : 0;
// console.log(index);
a[index].focus();
//按左键
} else if (e.keyCode === 37) {
// console.log(a.length)
index = index > 0 ? index - 1 : a.length - 1;
// console.log(index);
a[index].focus();
}
console.log(e.keyCode);
}
document.onclick = () => {
console.log("this is document!");
}
a.forEach(function(el) {
el.onclick = (e) => {
console.log("this is a!");
// e.stopPropagation();
}
})
</script>
</body>
</html>
你会发现如果我没有写注释的话,你压根就不清楚我到底在写哪个键对吧。这样对代码的可读性有很严重的影响,也对程序员写注释的要求更高了。
以下我来修改一下代码。首先是思路,我如果想要做自定义事件那么就需要分两个功能: 1. 注册事件 2. 监听事件。
监听事件没什么,也就是我们要完成就像原生的一样的去监听比如:
document. addEventListener("click",function(){
console.log("This is native !");
},false);
//以下监听应该和原生的事件是一致的
document. addEventListener("right.press",function(){
console.log("This is native !");
},false);
那么怎么去封装方法才最重要:
首先,先对整个键盘事件做一个控制器,然后设置一个初始化方法,传进DOM的时候将keydown事件全部监听:
var Controller = function(){
this,init = function (elem){
elem.removeEventListener("keydown",Controller.keydownCallback (e){
console.log("This is keydown !");
},false);)
}
elem.addEventListener("keydown", Controller.keydownCallback (e){
console.log("This is keydown !");
},false);)
}
}
然后呢,只要怎么才能出发keydown事件之后能够去触发我们想要自定义的press.right事件呢?当然是用dispatchEvent来触发。所以闲话不说我们先创建一个事件。根据MDN的资料来写一个函数:
Controller.press(key) {
//意在保存对象的变量还没有真正保存对象,就应该明确地让该变量保存null值
var evt = null;
try {
evt = new CustomEvent(key + '.press');
} catch (e) {
//兼容问题
evt = document.createEvent('Event');
evt.initEvent(key + '.press', true, true);
}
this.el.dispatchEvent(evt);
}
以上的代码把自定义按键事件创建和触发封装在了一个方法里。但是我们知道自定义事件是无法和原生的一样只要创建然后监听就可以了。它必须要手动去触发,但是我们不可能在项目中手动去触发自定义的事件。那么就需要有一个原生的事件来作为中间的桥梁。
Controller.keycodeCallback(e) {
swich(e.witch || e.keyCode){
case 39:
Controller.press("right");
break;
case 37:
Controller.press("left");
break;
default:
break;
}
}
这样,创建了一个自定义事件,通过触发keydown事件,然后触发自定事件。大致的原理是这样的。细节上的修改可以看看GitHub上的demo。
demo源码地址:keydownEvent.html。