想要清楚的對javascript的事件有一個詳細的瞭解,我們必須搞明白以下幾件事情:
首先,必須明白以下幾個概念
什麼是事件? 什麼是事件處理程序? 事件類型有哪些?事件流?事件冒泡?事件捕獲?事件對象? 常見瀏覽器兼容問題怎麼解決?
事件的概念
javas使我們有能力創建動態頁面,事件是可以被瀏覽器偵測到的行爲,比方說,我們可以在用戶點擊某一個按鈕的時候產生一個onclick來觸發某個函數,常見的事件有click,load,unload等
事件處理程序
響應某個事件的函數則稱爲事件處理程序,或者叫做事件偵聽器。
click、mousemove、load等都是事件的名稱,事件處理程序就是在事件的前面加上“on”,click事件的事件處理程序爲onclick。
事件類型
1.鼠標事件:
- click:單擊
- dbclick:雙擊
- mousedown:當用戶鼠標還未彈起觸發
- mouseup:當用戶釋放按鈕時觸發
- mouseover:當鼠標移到某個元素上方時觸發
- mouseout:當離開元素上方時觸發
- mousemove:當鼠標指針元素時觸發
2.鍵盤事件:
- keydown:當用戶按鍵盤上任意鍵觸發
- keypress:當用戶按鍵盤上的字符鍵觸發
- keyup:當用戶釋放鍵盤上的鍵觸發
3.HTML事件
- load:當整個頁面加載完成
- unload:當頁面完全卸載後在window上面觸發,或在框架集卸載後在框架集上觸發
- select:當用戶選擇文本框(input/textarea)中的一個或多個字符事觸發
- change:當文本框(input/textarea)內容且焦點後觸發
- focus:當頁面或元素焦點後在window及相關元素上觸發
- blur:當頁面或元素失去焦點時在window及相關元素上觸發
- submit:當用戶點擊提交按鈕時在form上觸發
- reset:當用戶點擊重置按鈕時在form上觸發
- resize:當窗口或框架的大小發生變化時在window或框架上觸發
- scroll:當用戶滾動帶滾動條的元素時觸發
4.滾輪事件:mousewheel(IE6+均支持)、DOMMouseScroll(Firefox支持的,與mousewheel效果一樣)。是使用鼠標滾輪時觸發的。
事件流
事件流描述的是從頁面中接收事件的順序,對於事件流,IE與NetScape提出了完全相反的順序,IE提出的是事件冒泡流,即事件開始的時候由最具體的接收,逐級向上傳播較爲不具體節點;網提出的時間捕獲流,即事件由最不具體的開始接收,然後逐級向下傳播到最具體的節點
window.onload= function(){
document.onclick=function(){
alert('document');
}
document.documentElement.onclick = function(){ //documentElement 屬性可返回文檔的根節點。
alert('html');
}
document.body.onclick=function () {
alert('body');
}
document.getElementById('box').onclick= function(){
alert('div');
}
document.getElementsByTagName('input')[0].onclick= function(evt){
alert('input');
//var e=evt||window.event;
//e.stopPropagation(); //W3C取消事件冒泡
//e.cancleBubble=true; //IE取消事件冒泡
//alert(typeof e.stopPropagation);
stop(evt);
}
}
//兼容(取消事件冒泡)
function stop(evt){
var e=evt||window.event;
if (typeof e.stopPropagation=='function') {
e.stopPropagation();
}else{
e.cancleBubble=true;
}
}
事件對象
在觸發DOM上的某個事件的時候,會產生一個事件對象event,而在這個對象中包含着所有與事件有關的信息,其中有兩個信息是我們最常用,分別是type和target,type表示的被觸發事件的類型,target表示的是事件的目標
//支持的DOM的瀏覽器可以直接獲取event;IE通過window.event獲取
document.onclick = function(evt){
//var e=event||window.event; //跨瀏覽器獲取event
// alert(e.type) //click
alert(getTarget(evt));
}
//跨瀏覽器獲取event目標
function getTarget(evt){
var e = event||window.event;
return e.target||e.srcElement;
}
事件綁定
1.傳統事件綁定(包括內聯模型和腳本模型)
腳本模型
//問題一:會覆蓋
window.onload = function(){
alert('li'); //被覆蓋了
}
window.onload=function(){
alert('lii'); //前者被覆蓋了 打印出lii
}
----------
解決覆蓋問題
//alert(typeof window.onload); //一開始沒有註冊window.onload 那麼就是null
window.onload = function(){
alert('li'); //被覆蓋了
}
if (typeof window.onload=='function') { //判斷是否存在上一個事件
var saved=null;
saved = window.onload; //保存上一個事件對象
};
//alert(typeof window.onload); //如果已經有window.onload 那麼返回的就是一個函數 所以可以進行判斷
window.onload=function(){
if(saved)saved(); //執行上一個事件window.onload=function(){};
alert('meiling'); //執行本事件
}
2.現代事件綁定(DOM2級模型)
//W3C自帶的兩個添加事件和刪除事件
//1.解決覆蓋問題
window.addEventListener('load',function(){
alert('lee');
},false) //lee
window.addEventListener('load',function(){
alert('le'); //le
},false)
//解決相同函數屏蔽的問題
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
function init(){
alert('lee'); //只會彈出一個lee
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="script.js"></script>
<style type="text/css">
.red{
width: 100px;
height: 100px;
background-color: red;
}
.blue{
width: 200px;
height: 200px;
background-color: blue;
}
</style>
</head>
<body>
<div id="box" class="red">測試</div>
</body>
</html>
//3.是否可以傳遞this(可以傳遞)
//js部分
window.addEventListener('load',function(){
var box = document.getElementById('box');
box.addEventListener('click',toBlue,false);
},false);
function toRed(){
this.className='red';
this.removeEventListener('click',toRed,false)
this.addEventListener('click',toBlue,false);
}
function toBlue(){
this.className='blue';
this.removeEventListener('click',toBlue,false)
this.addEventListener('click',toRed,false);
}
//4.添加一個額外的方法會不會被覆蓋,或者只能執行一次
window.addEventListener('load',function(){
var box = document.getElementById('box');
box.addEventListener('click',function(){
alert('lee');
},false);
box.addEventListener('click',toBlue,false);
},false);
function toRed(){
this.className='red';
this.removeEventListener('click',toRed,false)
this.addEventListener('click',toBlue,false);
}
function toBlue(){
this.className='blue';
this.removeEventListener('click',toBlue,false)
this.addEventListener('click',toRed,false);
}
IE事件處理函數
//IE事件處理函數 attachEvent() detachEvent()
//ie不支持捕獲,只支持冒泡, ie添加事件不能屏蔽重複的函數, ie中的this指向的是window而不是DOM對象
//1.覆蓋問題 ,解決了 但有不同 ,順序不同 倒過來的
window.attachEvent('onload',function(){
alert('leee');
})
window.attachEvent('onload',function(){
alert('lee');
})
window.attachEvent('onload',function(){
alert('le');
})
//2.相同函數屏蔽的問題 未解決 無法屏蔽
window.attachEvent('onload',init);
window.attachEvent('onload',init);
function init(){
alert('lee'); //彈出兩個lee
}
//3.是否可以傳遞this
window.attachEvent('onload',function(){
var box = document.getElementById('box');
box.attachEvent('onclick',function(){
// alert(this===box); //false
alert(this===window); //不能傳遞this true
})
})
// 4.添加一個額外的方法會不會被覆蓋,或者只能執行一次 解決了
window.attachEvent('onload',function(){
var box = document.getElementById('box');
box.attachEvent('onclick',function(){
alert('lee');
});
box.attachEvent('onclick',function(){
alert('le');
});
})
IE和w3c兼容事件切換器
//跨瀏覽器添加事件
function addEvent(obj,type,fn){
if (obj.addEventListener) {
obj.addEventListener(type,fn,false);
}else if (obj.attachEvent) {
obj.attachEvent('on'+type,fn);
}
}
//跨瀏覽器移除事件
function removeEvent(obj,type,fn){
if(obj.removeEventListener){
obj.removeEventListener(type,fn,false);
}else if(obj.detachEvent){
obj.detachEvent('on'+type,fn);
}
}
//跨瀏覽器獲取目標對象
function getTarget(evt){
if (evt.target) { //w3c
return evt.target;
}else if(window.event.srcElement){ //IE
return window.event.srcElement;
}
}
addEvent(window,'load',function(){
var box = document.getElementById('box');
addEvent(box,'click',toBlue);
})
function toRed(evt){
var that = getTarget(evt);
that.className='red';
removeEvent(that,'click',toRed);
addEvent(that,'click',toBlue);
}
function toBlue(evt){
var that = getTarget(evt);
that.className='blue';
removeEvent(that,'click',toBlue);
addEvent(that,'click',toRed);
}
其它
//跨瀏覽器添加事件
function addEvent(obj,type,fn){
if (obj.addEventListener) {
obj.addEventListener(type,fn,false);
}else if (obj.attachEvent) {
obj.attachEvent('on'+type,fn);
}
}
//跨瀏覽器移除事件
function removeEvent(obj,type,fn){
if(obj.removeEventListener){
obj.removeEventListener(type,fn,false);
}else if(obj.detachEvent){
obj.detachEvent('on'+type,fn);
}
}
//兼容 阻止默認行爲
function preDef(evt){
var e =evt||window.event;
if (e.preventDefault) {
e.preventDefault();
}else {
e.returnValue = false;
}
}
//上下文菜單事件:contextmenu(很常用) ,當我們右擊網頁的時候會出現windows自帶的菜單
//那麼我們可以使用contextmenu事件來修改我們指定的菜單,但前提是把右擊的默認行爲取消掉
addEvent(window,'load',function(){
var text = document.getElementById('text');
addEvent(text,'contextmenu',function(evt){
preDef(evt);
var menu = document.getElementById('menu');
var e =evt||window.event;
menu.style.left=e.clientX+'px'; //得到鼠標的座標
menu.style.top=e.clientY+'px';
menu.style.display='block';
addEvent(document,'click',function(){
menu.style.display='none';
})
})
})
//卸載前事件beforeunload,這個事件可以在幫助離開本頁時給出相應的提示,‘離開’或‘返回’操作
addEvent(window,'beforeunload',function(evt){
preDef(evt);
})