事件
具体看https://www.w3cschool.cn/jsref/dom-obj-event.html,这里讲的很详细。
鼠标相关: 点击onclick,双击ondblclick,移动onmousemove,鼠标按下onmousedown,鼠标抬起onmouseup,鼠标经过某元素onmouseover,鼠标离开某元素onmouseout。
键盘相关: 键盘按下onkeydown,键盘松开onkeyup,键盘按住onkeypress。
表单相关: 获取焦点onfocus,失去焦点onblur,内容改变onchange,表单提交onsubmit,重置onreset。
其他: 窗口或框架被调整大小onresize,图片或页面别加载完onload,元素滚动条滚动onscroll。
事件对象: event。由于ie和其他浏览器的不同,事件对象的获取也不同。事件对象有pageX/pageY,clentX/clientY等属性。
事件冒泡: 事件默认是冒泡的,冒泡指的是子元素的事件触发会触发祖先元素的同一事件。(就像你打了我的手,我也会感觉到,不知道这样会不会好理解点)。可以取消事件冒泡。
example1
<style>
#outer{width: 200px;height:200px;background-color:red;}
#inner{width:100px;height: 100px;background-color:blue;}
</style>
<div id="outer">
<div id="inner"></div>
</div>
<script>
outer.onclick = function(){
alert('outer');
}
inner.onclick = function(e){
e = e || event;
// 非ie
if(e.stopPropagation){
e.stopPropagation();
}else{
//ie
e.cancelBubble = true;
}
alert('inner');
}
//这里点击inner只会弹出一次inner,因为取消了inner的事件冒泡。
</script>
example2
<style>
ul{list-style: none;width: 100px;background-color: yellow;margin:0px;padding:0px;}
li{text-align: center;border:1px solid red;position: relative;}
.about{display: none;position: absolute;top:0;left:100px;width:100px;height: 50px;background-color: blue;}
</style>
<ul>
<li>1
<div class="about">aaa</div>
</li>
<li>2
<div class="about">aaa</div>
</li>
<li>3
<div class="about">aaa</div>
</li>
<li>4
<div class="about">aaa</div>
</li>
</ul>
<script>
var liDoms = document.getElementsByTagName('li');
for(var i=0,len=liDoms.length;i<len;i++){
liDoms[i].onmouseover = function(){
this.children[0].style.display='block';
}
liDoms[i].onmouseout = function(){
this.children[0].style.display='none';
}
}
</script>
注:上面的事件用css伪类:hover
也可以搞定,这里通过js事件完成的。
下面看一个div随着鼠标位置移动的位置移动的例子。说明事件对象e的pageX/pageY(获取鼠标在页面的位置,包括滚动条,但不兼容ie9-)和clientX/clientY(距离浏览器窗口的位置,不包括滚动条)的属性。
example3
<style>
body{height: 1300px;}
#box{width: 100px;height: 30px;background-color: black;color:white;position:absolute;top:0;left: 0}
</style>
<div id="box">xxx</div>
<script>
document.onmousemove = function(e){
e = e ||event;
var pos = getXY(e),
x = pos.x,
y = pos.y;
box.style.cssText = 'top:'+y+'px;left:'+x+'px;';
box.innerText = x+':'+y;
}
//获取鼠标距离浏览器的绝对位置
function getXY(e){
var pos = {x:0,y:0};
if(e.pageX){
pos.x = e.pageX;
pos.y = e.pageY;
}else{
pos.x = document.documentElement.scrollLeft+e.clientX;
pos.y = document.documentElement.scrollTop+e.clientY;
}
return pos;
}
</script>
example4
<style>
#box{position: absolute;width: 100px;height: 100px;background-color: red;}
</style>
<div id='box' style='top:0px;left:0;'></div>
<script>
box.onmousedown = function(e){
e = e || event;
var pos1 = getXY(e),
left = this.offsetLeft,
top = this.offsetTop;
//如果这里是this,鼠标过快会失效。我猜可能是鼠标太快会移出了box范围,但box移动刷新频率有限,还没来得及改变位置。
document.onmousemove = function(e){
e = e || event;
var pos2 = getXY(e),
x = pos2.x - pos1.x,
y = pos2.y - pos1.y;
box.style.left = left+x+'px';
box.style.top = top+y+'px';
}
document.onmouseup = function(){
this.onmouseup = null;
this.onmousemove = null;
}
}
//获取鼠标在页面的绝对位置
function getXY(e){
var pos = {x:0,y:0};
if(e.pageX){
pos.x = e.pageX;
pos.y = e.pageY;
}else{
pos.x = document.documentElement.scrollLeft+e.clientX;
pos.y = document.documentElement.scrollTop+e.clientY;
}
return pos;
}
</script>
监听事件的方法:ie9-用attachEvent()
方法,非ie9-用addEventListener()
。 addEventListener(type,fn,boolen)的三个参数中,type是监听的事件类型,fn是回调方法,boolean默认是false,表示由子元素向父元素依次触发事件,true则相反。(具体的可以看:https://my.oschina.net/u/1454562/blog/205010,感觉说的蛮靠谱的)
方法 | 描述 |
---|---|
addEventListener() | 允许在目标事件中注册监听事件(IE8= attachEvent()) |
dispatchEvent() | 允许发送事件到监听器上 (IE8 =fireEvent()) |
removeEventListener() | 运行一次注册在事件目标上的监听事件(IE8 =detachEvent()) |
不捕获事件: 由子元素依次像父元素执行的过程,对应参数是false。
捕获事件 : 父元素依次向子元素执行的过程
example5
<style>
*{margin: 0;padding: 0;}
a{text-decoration: none;color: #333;}
ul li{list-style: none;}
#box{width: 100px;height: 100px;background-color: red}
</style>
<div id="box"></div>
<script>
box.addEventListener('click', function(){
console.log('box1');
},false)
document.body.addEventListener('click', function(){
console.log('body')
},false)
document.documentElement.addEventListener('click', function(){
console.log('document')
},false)
window.addEventListener('click', function(){
console.log('window')
},false)
</script>
上面的html,点击box,会依次输出box1,body,document,window,因为是不捕获性事件。
example6
<style>
*{margin: 0;padding: 0;}
a{text-decoration: none;color: #333;}
ul li{list-style: none;}
#box{width: 100px;height: 100px;background-color: red}
</style>
<div id="box"></div>
<script>
box.addEventListener('click', function(){
console.log('box1');
})
box.addEventListener('click', function(){
console.log('box2');
})
</script>
上面的html,点击box,会依次输出box1,box2.
attachEvent(): IE8- 谁写在后谁先执行 IE9 谁写在前谁先执行.
写一个兼容的事件监听,如下:
example7
//兼容的事件监听
function bind(el, type, callBack){
if(el.addEventListener){
el.addEventListener(type, callBack);
}else{
el.attachEvent("on"+type, callBack);
}
}
动态的绑定事件用addEventListener去监听父元素,事件对象event有两个指向当前事件对象和实际事件对象的属性(e.currentTarget和e.target)。动态绑定可以节省资源。
<style>
*{margin: 0;padding: 0;}
a{text-decoration: none;color: #333;}
ul li{list-style: none;}
#list{width: 400px;margin: 30px auto;}
#list li{height: 30px;background-color: red;color: #fff;margin: 5px;}
</style>
<button id="btn">点我</button>
<ul id="list">
<li>1</li>
<li >2</li>
<li >3</li>
<li >4</li>
<a href="">123</a>
<span>1233</span>
<div>12312313</div>
</ul>
<div id="box"><span>啊哈哈</span></div>
<script>
list.addEventListener('click', function(e){
var target = e.target || e.srcElement;
if(target.tagName == 'LI'){
alert(target.innerText);
}
})
btn.onclick = function(){
var num = Math.random();
var str = "<li>"+num+"</li>"
list.innerHTML += str;
}
</script>