[^IE事件流是事件冒泡流;Netscape事件流式事件捕获流]:
事件冒泡: 事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点(文档)

事件捕获:有不太具体的节点更早的接收事件,而最具体的节点应该最后接收到事件
方法:addEventListener() 参数:类型,回调函数,默认false(冒泡阶段) 事件监听者
事件流:事件捕获阶段;处于目标阶段;事件冒泡阶段
var box = document.getElementById('box');box.addEventListener('click',function(){box.innerHTML += 'box\n';},true)//捕获阶段document.body.addEventListener('click',function(){box.innerHTML += 'body\n';},true)//捕获阶段document.documentElement.addEventListener('click',function(){box.innerHTML += 'html\n';},true)//捕获阶段document.addEventListener('click',function(){box.innerHTML += 'document\n';},true)//捕获阶段window.addEventListener('click',function(){box.innerHTML += 'window\n';},true)//捕获阶段//冒泡阶段box.addEventListener('click',function(){box.innerHTML += 'box\n';},false)document.body.addEventListener('click',function(){box.innerHTML += 'body\n';},false)document.documentElement.addEventListener('click',function(){box.innerHTML += 'html\n';},false)document.addEventListener('click',function(){box.innerHTML += 'document\n';},false)window.addEventListener('click',function(){box.innerHTML += 'window\n';},false)
得到的结果如下:
缺点: html+js无分离,后期不易维护
特别,注意不论在函数内还是函数外,this都是指向window对象
console.log(this);//指向window对象function test(){// console.log(this); 指向window对象document.getElementById('box').innerHTML += '1';}
优点:1.简单 2.跨浏览器
缺点:不能给同一个元素来绑定相同的事件处理程序,如果绑定了,会有覆盖现象
var box = document.getElementById('box');box.onclick = function(){this.innerHTML += 1;}//删除事件处理程序box.onclick = null;// 垃圾回收机制//缺点:不能给同一个元素来绑定相同的事件处理程序,如果绑定了,会有覆盖现象box.onclick = function(){this.innerHTML += 2;}
[^布尔值默认false是处于冒泡阶段,如果是true,是处于捕获阶段]:
IE8浏览器不支持DOM2处理程序
//没有事件覆盖现象setTimeout(function(){box.addEventListener('click',function(){this.innerHTML += 1;},false);},10)// //监听函数传参,可以用匿名函数包装一个监听函数box.addEventListener('click',function(){//监听匿名函数test(2);},false);// box.addEventListener('click',test(3),false);function test(x){alert(x);}
无效的移除事件的方式
//添加事件监听者box.addEventListener('click',function(){this.innerHTML += 1;},false);//移除事件box.removeEventListener('click',function(){this.innerHTML += 1;},false);
正确移除事件方式
function handler(){this.innerHTML += 1;}box.addEventListener('click',handler,false);box.removeEventListener('click',handler,false);
IE: attachEvent() detachEvent()
[^IE10以下浏览器可以使用 默认冒泡]:
var box = document.getElementById('box');box.attachEvent('onclick',function (){this.innerHTML += '1';})
1.DOM2级事件处理程序 addEventListener() IE8不支持, ie attachEvent()
[^IE8浏览器不支持DOM2处理程序]:
2.attachEvent()内部的this指向了window,我们要对this的指向也做兼容
ie8的写法如下:
var btn = document.getElementById('btn');function handler(){console.log(this.innerHTML);}btn.attachEvent('onclick',function(){handler.call(btn);//将方法绑定到对象上,这时候this指向btn对象})btn.addEventListener('click',fn,false); 默认为false,冒泡 this指向当前btn对象btn.attachEvent('onclick',fn) this指向window
全浏览器事件处理程序的兼容性代码:
addEvent(btn,'click',function(){console.log(this.innerHTML);})function addEvent(target,eventType,handler){if(target.addEventListener){//chrome ff safari都可以target.addEventListener(eventType,handler,false);//事件冒泡}else{target.attachEvent('on' + eventType,function(){handler.call(target);//将方法绑定到对象上,这时候this指向对象});}}
call方法可以改变this指向问题
console.log(this);//chrome ff 指向window对象var obj = {innerHTML : 'liujing'}function fn(){console.log(this.innerHTML);}//call方法可以改变this指向问题fn.call(obj);//chrome ff this指向obj对象fn.call();//chrome ff 指向window对象
相同点:如果同时出现HTML事件处理程序和DOM0级事件处理程序,DOM0级会覆盖HTML事件处理程序
不同点:
2.1 chrome,safari,FF浏览器以及IE11结果: DOM0级 DOM2级
2.2 IE9、10结果为:DOM0级 DOM2级 IE
2.3 ie8结果: DOM0级 IE
DOM0级事件处理程序
box.onclick = function(){this.innerHTML += 'DOM0级\n';}
DOM2级事件处理程序
if(box.addEventListener){box.addEventListener('click',function(){this.innerHTML += 'DOM2级\n';})}
IE级事件处理程序
if(box.attachEvent){box.attachEvent('onclick',function(){box.innerHTML += 'IE\n';})}
1.如何获取事件对象
2.事件目标
3.事件代理
4.事件冒泡
5.事件流阶段 eventPhase
6.取消默认事件 //javascript:void(0);
// 兼容性window.onload = function() {var box = document.getElementById('box');// 1.event对象是事件处理程序的第一个参数 ie8浏览器不兼容// ie8浏览器得到的结果是undefined,其它浏览器[object MouseEvent]box.onclick = function (e){console.log(e);this.innerHTML = e;}// 2.直接可以使用event变量 火狐浏览器低版本获取出来的是undefinedbox.onclick = function() {this.innerHTML = event;}// 兼容性代码box.onclick = function(e){console.log(e);// 兼容性写法e = e || window.event;//[object MouseEvent]box.innerHTML = e; //[object Event]}}
1.currentTarget属性:返回事件当前所在的节点,正在执行的监听函数所绑定的节点
[^target和srcElement功能一样]:
box.onclick = function (e){e = e || window.event;// console.log(e);//MouseEvent对象中的cancelBubble,cancelable;clientX;clientY属性//e,currentTarget 值是null //ie8低版本//e.srcElement值是li.itemconsole.log(e.currentTarget);//整个ul对象var items = document.getElementsByTagName('li');items[0].innerHTML = e.currentTarget;//[object HTMLListElement]}//监听的是li的父级节点ul
2.target属性:返回的是事件的实际目标对象
[^注意:target属性 ie8不支持]:
box.onclick = function (e){e = e || window.event;console.log(e.target);//<li class="item">1</li>console.log(e.target===this);//false// this对象跟e.currentTarget属性是一致的console.log(e.currentTarget===this);//true}
3.srcElement跟target功能是一致的,FF低版本的浏览器不支持
box.onclick = function(e) {e = e || window.event;// console.log(e.srcElement);//<li class="item">1</li>var target = e.target || e.srcElement;target.style.backgroundColor = 'red';}box.onmouseout = function(e) {e = e || window.event;var target = e.target || e.srcElement;target.style.backgroundColor = 'lightblue';}
css代码如下:
<style type="text/css">* {padding: 0;margin: 0;}ul {list-style: none;overflow: hidden;margin-top: 80px;}ul li {float: left;width: 100px;height: 30px;text-align: center;line-height: 30px;color: #fff;background-color: #000;margin: 0 10px;}</style>
html代码:
<ul id="box"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>
javascript代码:
window.onload = function() {// 常规方法实现// 1.获取标签var lis = document.getElementsByTagName('li');for(var i = 0; i < lis.length; i++){lis[i].onmouseover = function (){this.style.backgroundColor = 'blue';}lis[i].onmouseout = function (){this.style.backgroundColor = 'black';}}// 事件代理的方式实现 事件实际目标对象来实现// 事件代理应用: 事件实际目标对象target和srcElement属性完成// 优点: 提高性能以及降低代码的复杂度//ul 也被触发了var box = document.getElementById('box');box.onmouseover = function(e) {e = e || window.event;var target = e.target || e.srcElement;target.style.backgroundColor = 'blue';}box.onmouseout = function(e) {e = e || window.event;var target = e.target || e.srcElement;target.style.backgroundColor = 'black';}}
[^ul 也被触发了]:
//模拟未来的某个事件来添加对应的数据var box = document.getElementById('box');setTimeout(function(){var item = document.createElement('li');item.innerHTML = '6';box.appendChild(item);},100);
target本身就会因为事件捕获而指向具体的节点
// target本身就会因为事件捕获而指向具体的节点var box = document.getElementById('box');// 给未来的元素绑定事件,使用事件代理box.onmouseover = function (e){e = e || window.event;var target = e.target || e.srcElement;target.style.backgroundColor = 'blue';}box.onmouseout = function (e){e = e || window.event;var target = e.target || e.srcElement;target.style.backgroundColor = 'black';}
属性: bubbles; cancelBubble
方法:stopPropagation() ;stopImmediatePropagation()
1.bubbles 返回一个布尔值 表示当前事件是否会冒泡,只读 true:冒泡;false:非冒泡
[^大部分事件都会冒泡,但是focus blur scroll事件不会冒泡]:
var btn = document.getElementById('btn');var test = document.getElementById('test');btn.onclick = function(e) {e = e || window.event;console.log(e.bubbles);//true}test.onfocus = function (e){e = e || window.event;console.log(e.bubbles);//false}
2.stopPropagation()表示取消事件的进一步冒泡 无返回值,但是无法阻止同一事件的其它监听函数被调用
[^ie8浏览器不支持]:
btn.onclick = function(e){e = e || window.event;//阻止冒泡e.stopPropagation();this.innerHTML = '阻止冒泡';}document.body.onclick = function(e){e = e || window.event;console.log('body');}btn.addEventListener('click',function(e){e = e || window.event;e.stopPropagation();this.innerHTML = '修改了';},false);btn.addEventListener('click',function(e){e = e || window.event;this.style.backgroundColor = 'blue';//上面没有阻止这个操作},false);document.body.onclick = function (e){e = e || window.event;console.log('body');//阻止这个操作}
3.stopImmediatePropagation()既可以阻止冒泡,也可以阻止同一事件的其它监听函数被调用
btn.addEventListener('click', function(e) {e = e || window.event;e.stopImmediatePropagation();this.innerHTML = '修改了';}, false);btn.addEventListener('click', function(e) {e = e || window.event;this.style.backgroundColor = 'blue';}, false);document.body.onclick = function(e) {e = e || window.event;console.log('body');}
4.cancelBubble 属性用于阻止冒泡 可读写 默认值为false,当设置为true,cancelBubble可以取消事件冒泡
btn.onclick = function(e) {e = e || window.event;if(e.stopPropagation){e.stopPropagation();}else{e.cancelBubble = true;//全局浏览器支持}this.innerHTML = '修改了';}document.body.onclick = function(e) {e = e || window.event;console.log('body');}
兼容stopPropagation() stopImmediatePropagation()ie8不支持
[^e.cancelBubble = true;全浏览器都支持 不是标准写法]:
var handler = function (e){e = e || window.event;if(e.stopPropagation){e.stopPropagation();}else{e.cancelBubble = ture;}}
e.eventPhase 0 表示事件没有发生 1 表示捕获阶段 2目标阶段 3冒泡阶段
var btn = document.getElementById('btn');// 2 目标阶段btn.onclick = function (e){e = e || window.event;this.innerHTML = e.eventPhase + '阶段';console.log(e.eventPhase);}
// 1 捕获阶段document.body.addEventListener('click',function (e){e = e || window.event;console.log(e.eventPhase);},true);
// 3 冒泡阶段document.body.addEventListener('click',function (e){e = e || window.event;console.log(e.eventPhase);},false);
事件对象中两个方法 阻止默认事件: 方法:preventDefault() 属性:returnValue兼容ie8以下浏览器 return fasle
var apeland = document.getElementById('apeland');// 1.preventDefault() ie8不支持apeland.onclick = function (e){e = e || window.event;// 阻止冒泡// e.stopPropagation();// 阻止默认事件 ie8以下不支持// e.preventDefault();// 阻止默认事件 FF ie8以上不支持 ie9不支持// e.returnValue = false;// 兼容性写法if(e.preventDefault){e.preventDefault();}else{//兼容IE8以下的浏览器e.returnValue = false;}// 阻止默认事件return false;}
事件对象中提供了:clientX/Y,x/y,offsetX/Y,screenX/Y,pageX/pageY
clientX/Y和x/y: 相对于浏览器(浏览器的有效区域)的X轴和Y轴的距离
this.innerHTML = `clientX:${e.clientX};clientY:${e.clientY};X:${e.x};Y:${e.y}`;//clientX:8;clientY:8;X:8;Y:8
screenX/Y:相对于显示器屏幕的X轴和Y轴的距离
this.innerHTML = `screenX:${e.screenX};screenY:${e.screenY};`;//screenX:8;screenY:110;
pageX/Y: 相对于页面的X轴和Y轴的距离 滚动和clientY不同
this.innerHTML = `pageX:${e.pageX};pageY:${e.pageY};`;//pageX:8;pageY:1316;
offsetX/Y:相对于事件源的X轴和Y轴的距离
this.innerHTML = `offsetX:${e.offsetX};offsetY:${e.offsetY};`;//offsetX:0;offsetY:0;
事件
1.事件流
描述的是从页面接收事件的顺序
IE事件流是事件冒泡流,Netscape的事件流是事件捕获流
2.事件流阶段
(1)事件捕获阶段 (2)处于目标阶段 (3)事件冒泡阶段
事件捕获阶段:从最不具体的节点(window/document)接收事件 往具体的节点进行传播
事件冒泡阶段:从具体的节点开始接收事件,逐级往上传递到最不具体的节点。
3.事件对象
3.1 e.eventPhase 描述事件发生的阶段
事件捕获阶段 1
处于目标阶段 2
事件冒泡阶段 3
3.2 事件目标
e.currentTarget === this
e.target
e.srcElement(FF浏览器兼容)
//兼容性代码
var target = e.target || e.srcElement;
3.3 事件代理 也叫事件委托
3.4 取消默认行为
e.preventDefault();//ie8不兼容e.returnValue = false;//兼容return false;
3.5 事件冒泡
e.bubblesblur focus scroll三个事件返回值为falsee.stopPropagation(); //常用e.stopImmediatePropagation();e.cancelBubble = true;var handler = function(e){e = e || window.event;if(e.stopPropagation){e.stopPropagation();}else{e.cancelBubble = true;}}
4.事件处理程序
1) HTML事件处理程序
2) DOM0级事件处理程序
btn.onclick = function(e){e = e || window.event;}//有事件覆盖现象btn.onclick = function(e){e = e || window.event;}
3) DOM2级事件处理程序
btn.addEventListener('click',function (){},false);btn.addEventListener('click',function (){},false);var handler = function(){....}btn.addEventListener('click',handler,false);btn.removeEventListener('click',handler)
4) IE事件处理程序
btn.attachEvent('onclick',function(){//在ie中小心this 这个this指向了window})btn.detachEvent('onclick',function(){})处理this的指向问题,函数中的call(target);
5.2 screenX/Y
相对于当前的浏览器(有效的浏览器区域)的x轴和y轴的距离,与滚动条无关
5.3 pageX/Y
相对于显示器屏幕的x轴和y轴的距离
5.4 offsetX/Y
相对于页面的x轴和y轴的距离,如果有滚动条,包含整个页面,与滚动条有关
相对于事件源x轴和y轴的距离
css代码
<style type="text/css">*{margin:0px;padding:0px;}#box{width:430px;height:430px;border:1px solid #DDD;position:relative;margin:50px;}#small_box{width:430px;height:430px;position:relative;}#small_box #mask{position:absolute;width:210px;height:210px;background:url(images/dotted.png) repeat;top:0px;left:0px;display:none;}#big_box{position:absolute;left:440px;top:0px;width:430px;height:430px;border:1px solid #ddd;overflow:hidden;display:none;}#big_box img{position:absolute;z-index:5;}</style>
html代码
<div id="box"><div id="small_box"><img src="images/photo.jpg"><span id="mask"></span></div><div id="big_box"><img src="images/photo01.jpg"></div></div>
javascript代码
window.onload = function(){//1.获取需要的标签var box = document.getElementById('box');var small_box = box.children[0];var big_box = box.children[1];var small_img = small_box.children[0];var mask = small_box.children[1];var big_img = big_box.children[0];//2.监听鼠标移动small_box.onmouseover = function(){//2.1让遮罩层和大盒子显示出来mask.style.display = 'block';big_box.style.display = 'block';//2.2监听鼠标移动small_box.onmousemove = function(e){e = e || window.event;//2.3求出小盒子移动的水平和垂直的距离var moveX = e.clientX - small_box.offsetLeft - box.offsetLeft - mask.offsetWidth*0.5;//small_box.offsetLeft 为0var moveY = e.clientY - small_box.offsetTop - box.offsetTop - mask.offsetHeight*0.5;//2.4移动边界处理if(moveX < 0){moveX = 0;}else if(moveX >= small_box.offsetWidth - mask.offsetWidth){moveX = small_box.offsetWidth - mask.offsetWidth;}if(moveY < 0){moveY = 0;}else if(moveY >= small_box.offsetWidth - mask.offsetWidth){moveY = small_box.offsetHeight - mask.offsetHeight;}//2.5让小盒子移动起来mask.style.left = moveX + 'px';mask.style.top = moveY + 'px';//2.6大图移动起来//公式:moveX/大图移动的距离 = (small_box宽度-mask宽度)/(big_img宽度-big_box宽度);// var x = moveX / (small_box.offsetWidth - mask.offsetWidth);// var y = moveY / (big_img.offsetWidth - big_box.offsetWidth);var scale = (big_img.offsetWidth - big_box.offsetWidth)/(small_box.offsetWidth - mask.offsetWidth);// console.log(small_box.offsetWidth);//430// console.log(mask.offsetWidth);//210// console.log(big_img.offsetWidth);//800// console.log(big_box.offsetWidth);//432// big_img.style.left = - x * (big_img.offsetWidth - big_box.offsetWidth) +'px';// big_img.style.top = - y * (big_img.offsetHeight - big_box.offsetHeight) +'px';big_img.style.left = - moveX * scale +'px';big_img.style.top = - moveY * scale +'px';// var lw = mask.offsetLeft;// var lh = mask.offsetTop;// var rate = big_img.offsetWidth/big_box.offsetWidth;// // var rate = small_box.offsetWidth/mask.offsetWidth;// var newX = lw * 1.68;// var newY = lh * 1.68;// big_img.style.left = -newX +'px';// big_img.style.top = -newY +'px';}}small_box.onmouseout = function(e){mask.style.display = 'none';big_box.style.display = 'none';}}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号