title: 39-事件的绑定和事件对象Event
publish: true
绑定事件的两种方式/DOM事件的级别
我们在之前的一篇文章《04-JavaScript/22-DOM简介和DOM操作》中已经讲过事件的概念。这里讲一下绑定(注册)事件的两种方式,我们以onclick事件为例。
DOM0的写法:onclick
element.onclick = function () {
}
|
举例:
<body> <button>点我</button> <script> var btn = document.getElementsByTagName("button")[0];
btn.onclick = function () { console.log("事件1"); }
btn.onclick = function () { console.log("事件2"); }
</script> </body>
|
点击按钮后,上方代码的打印结果:
我们可以看到,DOM对象.事件 = 函数
的这种绑定事件的方式:一个元素的一个事件只能绑定一个响应函数。如果绑定了多个响应函数,则后者会覆盖前者。
DOM2的写法:addEventListener(高版本浏览器)
element.addEventListener('click', function () {
}, false);
|
参数解释:
举例:
<body> <button>按钮</button> <script> var btn = document.getElementsByTagName("button")[0];
btn.addEventListener("click", fn1); btn.addEventListener("click", fn2);
function fn1() { console.log("事件1"); }
function fn2() { console.log("事件2"); }
</script> </body>
|
点击按钮后,上方代码的打印结果:
我们可以看到,addEventListener()
这种绑定事件的方式:
一个元素的一个事件,可以绑定多个响应函数。不存在响应函数被覆盖的情况。执行顺序是:事件被触发时,响应函数会按照函数的绑定顺序执行。
addEventListener()中的this,是绑定事件的对象。
addEventListener()
不支持 IE8 及以下的浏览器。在IE8中可以使用attachEvent
来绑定事件(详见下一小段)。
DOM2的写法:attachEvent(IE8及以下版本浏览器)
element.attachEvent('onclick', function () {
});
|
参数解释:
参数1:事件名的字符串(注意,有on)
参数2:回调函数:当事件触发时,该函数会被执行
举例:
<body> <button>按钮</button> <script> var btn = document.getElementsByTagName('button')[0];
btn.attachEvent('onclick', function() { console.log('事件1'); });
btn.attachEvent('onclick', function() { console.log('事件2'); }); </script> </body>
|
在低版本的IE浏览器上,点击按钮后,上方代码的打印结果:
我们可以看到,attachEvent()
这种绑定事件的方式:
兼容性写法
上面的内容里,需要强调的是:
既然这两个写法的this
不同,那么,有没有一种兼容性的写法可以确保这两种绑定方式的this是相同的呢?我们可以封装一下。代码如下:
<body> <button>按钮</button> <script> var btn = document.getElementsByTagName('button')[0];
myBind(btn , "click" , function(){ alert(this); });
function myBind(element , eventStr , callback){ if(element.addEventListener){ element.addEventListener(eventStr , callback , false); }else{
element.attachEvent("on"+eventStr , function(){ callback.call(element); }); } }
</script> </body>
|
事件对象
当事件的响应函数被触发时,会产生一个事件对象event
。浏览器每次都会将这个事件event
作为实参传进之前的响应函数。
这个对象中包含了与当前事件相关的一切信息。比如鼠标的坐标、键盘的哪个按键被按下、鼠标滚轮滚动的方向等。
获取 event 对象(兼容性问题)
所有浏览器都支持event对象,但支持的方式不同。如下。
(1)普通浏览器的写法是 event
。比如:
(2)ie 678 的写法是 window.event
。此时,事件对象 event 是作为window对象的属性保存的。
于是,我们可以采取一种兼容性的写法。如下:
event = event || window.event;
|
代码举例:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script> document.onclick = function (event) { event = event || window.event;
console.log(event); console.log(event.timeStamp); console.log(event.bubbles); console.log(event.button); console.log(event.pageX); console.log(event.pageY); console.log(event.screenX); console.log(event.screenY); console.log(event.target); console.log(event.type); console.log(event.clientX); console.log(event.clientY); } </script> </body> </html>
|
event 属性
event 有很多属性,比如:
由于pageX 和 pageY的兼容性不好,我们可以这样做:
- 鼠标在页面的位置 = 滚动条滚动的距离 + 可视区域的坐标。
Event举例
举例1:使 div 跟随鼠标移动
代码实现:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title></title> <style type="text/css"> #box1 { width: 100px; height: 100px; background-color: red;
position: absolute; } </style>
<script type="text/javascript"> window.onload = function() {
var box1 = document.getElementById("box1");
document.onmousemove = function(event) { event = event || window.event;
var pagex = event.pageX || scroll().left + event.clientX; var pagey = event.pageY || scroll().top + event.clientY;
box1.style.left = pagex + "px"; box1.style.top = pagey + "px"; }; };
function scroll() { return { left: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop, right: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft }; } </script> </head> <body style="height: 1000px;width: 2000px;"> <div id="box1"></div> </body> </html>
|
举例2:获取鼠标距离所在盒子的距离
关键点:
鼠标距离所在盒子的距离 = 鼠标在整个页面的位置 - 所在盒子在整个页面的位置
|
代码演示:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> .box { width: 300px; height: 200px; padding-top: 100px; background-color: pink; margin: 100px; text-align: center; font: 18px/30px "simsun"; cursor: pointer; } </style> </head> <body> <div class="box">
</div>
<script src="animate.js"></script> <script>
var div = document.getElementsByTagName("div")[0];
div.onmousemove = function (event) {
event = event || window.event; var pagex = event.pageX || scroll().left + event.clientX; var pagey = event.pageY || scroll().top + event.clientY; var targetx = pagex - div.offsetLeft; var targety = pagey - div.offsetTop; this.innerHTML = "鼠标在盒子中的X坐标为:" + targetx + "px;<br>鼠标在盒子中的Y坐标为:" + targety + "px;" }
</script> </body> </html>
|
实现效果:
举例3:商品放大镜
代码实现:
(1)index.html:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; }
.box { width: 350px; height: 350px; margin: 100px; border: 1px solid #ccc; position: relative; }
.big { width: 400px; height: 400px; position: absolute; top: 0; left: 360px; border: 1px solid #ccc; overflow: hidden; display: none; }
.mask { width: 175px; height: 175px; background: rgba(255, 255, 0, 0.4); position: absolute; top: 0; left: 0; cursor: move; display: none; }
.small { position: relative; }
img { vertical-align: top; } </style>
<script src="tools.js"></script> <script> window.onload = function () {
var box = document.getElementsByClassName("box")[0]; var small = box.firstElementChild || box.firstChild; var big = box.children[1]; var mask = small.children[1]; var bigImg = big.children[0];
small.onmouseenter = function () { show(mask); show(big); } small.onmouseleave = function () { hide(mask); hide(big); }
small.onmousemove = function (event) { event = event || window.event;
var pagex = event.pageX || scroll().left + event.clientX; var pagey = event.pageY || scroll().top + event.clientY;
var x = pagex - box.offsetLeft - mask.offsetWidth / 2; var y = pagey - box.offsetTop - mask.offsetHeight / 2;
if (x < 0) { x = 0; } if (x > small.offsetWidth - mask.offsetWidth) { x = small.offsetWidth - mask.offsetWidth; } if (y < 0) { y = 0; } if (y > small.offsetHeight - mask.offsetHeight) { y = small.offsetHeight - mask.offsetHeight; }
console.log(small.offsetHeight); mask.style.left = x + "px"; mask.style.top = y + "px";
var bili = bigImg.offsetWidth / small.offsetWidth;
var xx = bili * x; var yy = bili * y;
bigImg.style.marginTop = -yy + "px"; bigImg.style.marginLeft = -xx + "px"; } } </script> </head> <body> <div class="box"> <div class="small"> <img src="images/001.jpg" alt=""/> <div class="mask"></div> </div> <div class="big"> <img src="images/0001.jpg" alt=""/> </div> </div> </body> </html>
|
(2)tools.js:
function show(ele) { ele.style.display = "block"; }
function hide(ele) { ele.style.display = "none"; }
function scroll() { if (window.pageYOffset != null) { return { left: window.pageXOffset, top: window.pageYOffset } } else if (document.compatMode === "CSS1Compat") { return { left: document.documentElement.scrollLeft, top: document.documentElement.scrollTop } } return { left: document.body.scrollLeft, top: document.body.scrollTop } }
|
效果演示:
我的公众号
想学习更多技能?不妨关注我的微信公众号:千古壹号(id:qianguyihao
)。
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外: