event事件對象
在觸發(fā)DOM上某個事件時,會產(chǎn)生一個事件對象event,這個對象包含著所有事件相 關(guān)的信息,包含導致事件的元素,事件的類型以及其他的與特定事件相關(guān)的信息。
它是事件處理函數(shù)的第一個(隱藏)的參數(shù),可以通過arguments[0]來獲取。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<button id="btn">GET</button>
</body>
<script>
btn.onclick=function(){
console.log(arguments[0])
}
</script>
</html>
此時會打印出一系列的鼠標事件
btn.onclick=function(event){
var event = event || window.event
console.log(event)
}
效果等同上方,IE下取事件是在window下的,此處是個兼容
event.button
如果當前event是鼠標事件,則會有一個button屬性,它是一個數(shù)字
0代表鼠標按下了左鍵 1代表按下了滾輪 || 2代表按下了右鍵(不介紹低版本IE)
<script>
document.onmousedown=function(ev){
var ev=ev||window.event;
alert(ev.button);//012
}
</script>
在頁面中點擊即可,作為了解一下
鼠標事件中獲取鼠標的位置屬性介紹(clientX、pageX、offsetX、screenX)
clientX,clientY:鼠標相對于可視區(qū)的位置。
pageX,pageY:鼠標相對于文檔的位置
offsetX,offsetY:鼠標相對于操作元素(鼠標點擊元素)到盒子邊緣(左上)的位置.
screenX,screenY:鼠標相對于顯示屏的位置.
document.onmousedown=function(ev){
var ev=ev||window.event;
console.log('可視區(qū)的位置X:'+ev.clientX);
console.log('可視區(qū)的位置Y:'+ev.clientY);
console.log('文檔的位置X:'+ev.pageX);
console.log('文檔的位置Y:'+ev.pageY);
console.log('對于操作元素的位置X:'+ev.offsetX);
console.log('對于操作元素的位置Y:'+ev.offsetY);
console.log('顯示屏的位置X:'+ev.screenX);
console.log('顯示屏的位置Y:'+ev.screenY);
}
這個還是得自己多測試加強記憶,寫個小demo
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.box{
width: 100px;
height: 100px;
background: red;
position: absolute;
cursor: move;
}
</style>
</head>
<body>
<div class="box"></div>
<script type="text/javascript">
var oBox=document.querySelector('.box');
document.onmousemove=function(ev){
var ev=ev||window.event;
oBox.style.cssText='left:'+(ev.clientX-oBox.offsetWidth/2)+'px;top:'+(ev.clientY-oBox.offsetHeight/2)+'px;';
}
</script>
</body>
</html>
自行復制瀏覽一下即可
鍵盤事件
onkeydown + onkeyup =onpress(按下+彈起=點擊)
每一個鍵盤字母都對應(yīng)自己的keyCode碼,可以測試一下
document.onkeydown=function(ev){
var ev=ev||window.event;
alert(ev.keyCode);//獲取鍵碼
}
寫個小demo,控制盒子移動(w,s,a,d)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
div{
width: 200px;
height: 200px;background: red;
position: absolute;
left:400px;top:100px;
}
</style>
</head>
<body>
<div></div>
<script type="text/javascript">
var oDiv=document.querySelector('div');
document.onkeydown=function(ev){
var ev=ev||window.event;
if(ev.keyCode==87){
oDiv.style.top=oDiv.offsetTop-10+'px';
}else if(ev.keyCode==83){
oDiv.style.top=oDiv.offsetTop+10+'px';
}else if(ev.keyCode==65){
oDiv.style.left=oDiv.offsetLeft-10+'px';
}else if(ev.keyCode==68){
oDiv.style.left=oDiv.offsetLeft+10+'px';
}
}
</script>
</body>
</html>
組合鍵
ctrlKey、altKey、shiftKey
document.onkeydown=function(ev){
var ev=ev||window.event
if(ev.keyCode==13&& ev.ctrlKey){ //摁下ctrl與回車 才執(zhí)行
alert(1)
}
if(ev.keyCode==13&& ev.altKey){ //摁下alt 與回車 才執(zhí)行
alert(2)
}
}
先按組合鍵測試哦
js事件流
事件流描述的是從頁面中接收事件的順序,事件可以分為冒泡事件與非冒泡事件
事件的冒泡
IE 的事件流叫做事件冒泡,即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節(jié)點)接收,然后逐級向上傳播到較為不具體的節(jié)點(文檔) 。
取消冒泡:具體元素對象(冒泡元素)的事件不會冒泡到父級(外層)。
非標準(ie8及以下): ev.cancelBubble=true;
標準:ev.stopPropagation();
注意的點是,冒泡的順序,逐級向上傳播到較為不具體的節(jié)點,寫個demo可測試
<!DOCTYPE html>
<html id="html1">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#small{
width: 200px;
height:200px;
border-radius: 50%;
background: red;
}
#middle{
width: 200px;
height:200px;
border-radius: 50%;
background: green;
padding: 100px;
}
#big{
width: 400px;
height:400px;
border-radius: 50%;
background: blue;
padding: 100px;
margin:0 auto;
}
</style>
</head>
<body id="body1">
<div id="big">
<div id="middle">
<div id="small"></div>
</div>
</div>
<script type="text/javascript">
//事件流:從頁面中接收事件的順序
var small=document.querySelector('#small');
var middle=document.querySelector('#middle');
var big=document.querySelector('#big');
function fn(){
alert(this.id);
}
small.onclick=fn;
middle.onclick=fn;
big.onclick=fn;
document.body.onclick=fn;
document.documentElement.onclick=fn;
</script>
</body>
</html>
一共五個事件,如果我點擊紅圈,也就是先彈small,然后逐級向上釋放,接著談綠色middle,藍色big,然后是body,最后是html
如果我點擊綠圈,紅色就不觸發(fā),綠色的父級逐漸觸發(fā),這個就是事件的冒泡,平時我們點擊元素的時候相當于也點擊了body,document,只是我們沒有給父元素設(shè)置事件而已
冒泡的應(yīng)用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<button>顯示</button>
<div style="width: 150px;height: 250px;background: red;display: none;"></div>
<script type="text/javascript">
var oBtn=document.querySelector('button');
var oDiv=document.querySelector('div');
oBtn.onclick=function(ev){
var ev=ev||window.event;
oDiv.style.display='block';
//ev.stopPropagation();//標準瀏覽器取消冒泡
}
document.onclick=function(){
oDiv.style.display='none';
}
</script>
</body>
</html>
我這里沒有取消冒泡,在點擊按鈕的時候,事件會冒泡到document讓其隱藏,所以點擊按鈕無法顯示,關(guān)閉冒泡之后就可以顯示元素了,我們平時寫事件的時候需要注意一下
阻止默認事件
瀏覽器有許多默認事件,比如瀏覽器的右鍵出現(xiàn)一組選項框,比如我們表單元素中的submit的默認提交事件以及reset的重置事件,還有a標簽的跳轉(zhuǎn)事件,很多
document.oncontextmenu=function(ev){ //右鍵事件
return false
}
取消默認事件很簡單,使用return false
ev.preventDefault(); 標準瀏覽器阻止默認事件,DOM事件使用此方法取消默認事件。
ev.returnValue = false; 非標準瀏覽器(IE8)阻止默認事件
document.oncontextmenu=function(ev){ //右鍵事件
alert(1)
ev.preventDefault()
// return false
}
因為JS是單線程語言,如果我們在不取消其默認事件的前提下,給右鍵點擊增加一個事件,彈窗來一個,會先出彈窗再顯示選項框,由此可見自定義事件優(yōu)先于默認事件,基于這個原理我們在自定義事件后方返回函數(shù)false不讓其往下運行即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
.box{
width: 200px;
height: 300px;
background: red;
position: absolute;
display: none;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
<script>
var oBox=document.querySelector('.box');
document.oncontextmenu=function(ev){ //右鍵事件
var ev=ev||window.event;
oBox.style.display='block';
oBox.style.left=ev.clientX+'px';
oBox.style.top=ev.clientY+'px';
return false
}
document.onclick=function(){
oBox.style.display='none';
}
</script>
</html>
可復制 瀏覽一下
其他事件也可以由此出發(fā),取消其默認行為
<body>
<a onclick="return false">百度</a>
<form action="http://www.baidu.com">
<input type="submit" onclick="return false" />
</form>
</body>
DOM2級事件
<script>
document.onclick=function(){//一個元素上面綁定一個事件
alert(123);
}
document.onclick=function(){//多個事件就會出現(xiàn)覆蓋。
alert(456);
}
//document.onclick=null //取消事件
</script>
上面的js很明顯,只彈出456,同元素同事件會覆蓋,很容易理解,那如果我們要點擊出現(xiàn)兩個事件怎么辦呢
DOM事件綁定:一個元素上面綁定多個事件。
基本格式
元素對象.addEventListener(事件類型,函數(shù),是否捕獲);標準瀏覽器
事件類型:不能添加on,click/mouseover...
函數(shù):普通函數(shù)名稱或者函數(shù)體。
是否捕獲:false:冒泡(默認) true:捕獲
第三個參數(shù),是否捕獲冒泡先不介紹,先無視
IE事件綁定和DOM事件綁定(標準瀏覽器)的區(qū)別
ie瀏覽器:attachEvent(事件類型,函數(shù));
事件類型:添加on onclick
函數(shù):普通函數(shù)名稱或者函數(shù)體。
1.參數(shù)不一樣
2.執(zhí)行順序不一樣
3.事件類型不一樣
4.this指向不一樣
第三個參數(shù)默認為false冒泡
<script>
function a(){
alert('a');
}
function b(){
alert('b');
}
function c(){
alert('c');
}
document.addEventListener('click',a); //沒有on
document.addEventListener('click',b);
document.addEventListener('click',c);
/*document.attachEvent('onclick',a); IE事件 可無視 很煩
document.attachEvent('onclick',b);
document.attachEvent('onclick',c);*/
</script>
此時點擊document 順序彈出abc
removeEventListener()/detachEvent() 移除事件綁定的參數(shù)和添加事件綁定是一致的。后面是IE移除
document.removeEventListener('click',a)
此時就不彈a了
簡易事件封裝
function addEvent(obj,event,fn){
if(obj.addEventListener){//判斷條件采用屬性判斷,如果存在屬性就不是IE
obj.addEventListener(event,fn,false);
}else{
obj.attachEvent('on'+event,fn);
}
}
//事件移除的封裝
function removeEvent(obj,event,fn){
if(obj.removeEventListener){
obj.removeEventListener(event,fn,false);
}else{
obj.detachEvent('on'+event,fn);
}
}
addEvent(document,'click',a);
addEvent(document,'click',b);//綁定
removeEvent(document,'click',b)//移除
addEvent(document,'click',c);
事件流的捕獲
<!DOCTYPE html>
<html id="html1">
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#small{
width: 200px;
height:200px;
border-radius: 50%;
background: red;
}
#middle{
width: 200px;
height:200px;
border-radius: 50%;
background: green;
padding: 100px;
}
#big{
width: 400px;
height:400px;
border-radius: 50%;
background: blue;
padding: 100px;
margin:0 auto;
}
</style>
</head>
<body id="body1">
<div id="big">
<div id="middle">
<div id="small"></div>
</div>
</div>
<script type="text/javascript">
var small=document.querySelector('#small');
var middle=document.querySelector('#middle');
var big=document.querySelector('#big');
function fn(){
alert(this.id);
}
/*small.onclick=fn;
middle.onclick=fn;
big.onclick=fn;
document.body.onclick=fn;
document.documentElement.onclick=fn;*/
function addEvent(obj,event,fn,bool){
if(obj.addEventListener){
obj.addEventListener(event,fn,bool);
}else{
obj.attachEvent('on'+event,fn);
}
}
addEvent(small,'click',fn,true);
addEvent(middle,'click',fn,true);
addEvent(big,'click',fn,true);
addEvent(document.body,'click',fn,true);
addEvent(document.documentElement,'click',fn,true);
</script>
</body>
</html>
依舊是之前三個圓,注意上方的最后一個參數(shù)是true,之前說過DOM事件的綁定第三個參數(shù)是個布爾值,我這里封裝了一下方法,多了一個元素參數(shù),此時我們點哪個都是最后一個才彈
比如我們點最小的紅圈,先彈html 然后body 然后依次遞減,但是我這個布爾值是可以更改的,如果為fasle則是冒泡,我修改其中一兩個看看效果
addEvent(small,'click',fn,false);//冒泡
addEvent(middle,'click',fn,true);//捕獲
addEvent(big,'click',fn,false);//冒泡
addEvent(document.body,'click',fn,true);//捕獲
addEvent(document.documentElement,'click',fn,false);//冒泡
此時我要點最小的紅圈,彈的順序是
body--middle--small--big--html
如果我點big 籃圈,彈的順序是
body--big--html
如果我點的是綠圈,彈的順序是
body--middle--big--html
事件流的順序:捕獲---目標---冒泡,多套幾個圈 多測幾次就可以更深入理解了
事件委托的應(yīng)用
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text" id="text" /><input type="button" value="發(fā)布" id="btn" />
<ul id="ul1">
<li>55555555</li>
<p>pppppppppp</p>
</ul>
<script type="text/javascript">
var oT=document.getElementById('text');
var oBtn=document.getElementById('btn');
var oUl=document.getElementById('ul1');
oBtn.addEventListener('click',function(){
var cLi=document.createElement('li');
cLi.innerHTML=oT.value;
oUl.appendChild(cLi);
oT.value='';
},false);
//事件委托的應(yīng)用
oUl.onclick=function(ev){
var ev=ev||window.event;
//target:獲取目標元素,點擊的元素對象。
var ele=ev.target||ev.srcElement;//獲取當前點擊目標元素
alert(ele.nodeName);//獲取當前元素的名稱(大寫的)
if(ele.nodeName=='LI'){//一定要判斷當前點擊的元素,就是我們需要控制的元素。
alert(ele.innerHTML);
}
}
</script>
</body>
</html>
注意我點的是UL,從外面找里面找到元素,如果我們在寫邏輯的時候發(fā)現(xiàn)這個元素很難找的時候,就可以使用這種方法
拖拽效果
這個效果其實在別的文章中寫過,簡易的再寫一次,多敲一遍總是好的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0
}
div{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0
}
</style>
</head>
<body>
<div id="div"></div>
</body>
<script>
div.onmousedown=function(ev){
var ev=ev||window.event
//鼠標按下的時候獲取短線
var shortx=ev.offsetX;
var shorty=ev.offsetY;
document.onmousemove=function(ev){ //這里為什么使用document 根據(jù)冒泡原理應(yīng)該很好理解了吧
var ev=ev||window.event;//在移動的時候重新獲取,不斷變化,用移動時的鼠標位置。
div.style.left=ev.clientX-shortx+'px';
div.style.top=ev.clientY-shorty+'px';
}
div.onmouseup=function(){
document.onmousemove=null
div.onmouseup=null
}
}
</script>
</html>
最簡單的一個拖拽,需要注意的是onmouseup要寫在onmousedown里面,如果寫外面就執(zhí)行一次,之后將無法取消move事件,如果我們不想讓他超出瀏覽器,寫個判斷
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0
}
div{
width: 100px;
height: 100px;
background: red;
position: absolute;
left: 0;
top: 0
}
</style>
</head>
<body>
<div id="div"></div>
</body>
<script>
div.onmousedown=function(ev){
var ev=ev||window.event
//鼠標按下的時候獲取短線
var shortx=ev.offsetX;
var shorty=ev.offsetY;
document.onmousemove=function(ev){ //這里為什么使用document 根據(jù)冒泡原理應(yīng)該很好理解了吧
var ev=ev||window.event;//在移動的時候重新獲取,不斷變化,用移動時的鼠標位置。
var l=ev.clientX-shortx;//水平 鼠標的x坐標減去鼠標到div左邊的距離就是div的left值
var t=ev.clientY-shorty;//垂直
if(l<=0){
l=0;
}else if(l>=document.documentElement.clientWidth-div.offsetWidth){
l=document.documentElement.clientWidth-div.offsetWidth;
}
if(t<0){
t=0;
}else if(t>=document.documentElement.clientHeight-div.offsetHeight){
t=document.documentElement.clientHeight-div.offsetHeight
}
div.style.left=l+'px';
div.style.top=t+'px';
}
div.onmouseup=function(){
document.onmousemove=null
div.onmouseup=null
}
}
</script>
</html>
這個邏輯應(yīng)該不難
然鵝有些元素是不允許拖拽的,比如img,其實使用return false就可以,我們試著封裝一個函數(shù)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0
}
img{
position: absolute;
left: 0;
top: 0
}
</style>
</head>
<body>
<img id="img" src="http://img2.imgtn.bdimg.com/it/u=2830140111,3261939339&fm=26&gp=0.jpg" />
</body>
<script>
function drag(el){
el.onmousedown=function(ev){
var ev=ev||window.event;
shortx=ev.offsetX;
shorty=ev.offsetY;
document.onmousemove=function(ev){
var ev=ev||window.event;//重新獲取,不斷變化,用移動時的鼠標位置。
var l=ev.clientX-shortx;//水平
var t=ev.clientY-shorty;//垂直
el.style.left=l+'px';
el.style.top=t+'px';
}
el.onmouseup=function(){
document.onmousemove=null;
el.onmouseup=null
}
return false
}
}
drag(img)
</script>
</html>
這樣我們只需要傳遞元素即可了
碰撞檢測
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.box1{
width: 200px;
height: 200px;
background: red;
position: absolute;
z-index: 2;
}
.box2{
width: 200px;
height: 200px;
background: blue;
position: absolute;
left:800px;
top:200px;
}
</style>
</head>
<body>
<div class="box1">1</div>
<div class="box2">2</div>
<script type="text/javascript">
var oBox1=document.querySelector('.box1');
var oBox2=document.querySelector('.box2');
var shortx=0;
var shorty=0;
oBox1.onmousedown=function(ev){
//鼠標按下求短線。
var ev=ev||window.event;
shortx=ev.offsetX;
shorty=ev.offsetY;
document.onmousemove=function(ev){
var ev=ev||window.event;//重新獲取,不斷變化,用移動時的鼠標位置。
var l=ev.clientX-shortx;//水平
var t=ev.clientY-shorty;//垂直
oBox1.style.left=l+'px';
oBox1.style.top=t+'px';
if( !((oBox1.offsetLeft+oBox1.offsetWidth)<oBox2.offsetLeft || oBox1.offsetLeft>oBox2.offsetLeft+oBox2.offsetWidth || (oBox1.offsetTop+oBox1.offsetHeight)<oBox2.offsetTop || oBox1.offsetTop>oBox2.offsetTop+oBox2.offsetHeight) ){
oBox2.style.background='green';
}else{
oBox2.style.background='blue';
}
}
document.onmouseup=function(){//松開鼠標,不再移動了
document.onmousemove=null;
document.onmouseup=null;
}
return false;//取消默認事件
}
</script>
</body>
</html>
這個代碼就不解釋了,看不懂多看幾遍 主要是判斷的地方