1. 程式人生 > >JS事件詳解(二) —— 事件處理程式(事件的繫結)

JS事件詳解(二) —— 事件處理程式(事件的繫結)

事件繫結方法

方法一:直接在HTML標籤中繫結

在html標籤中新增“on”+事件名稱的屬性來繫結事件

事件處理程式可直接寫在屬性值當中

<div class="demo" onclick="console.log(this)"></div>  // this指向的是當前DOM物件

這種事件處理程式的作用域很特別,可以像區域性變數一樣直接訪問document及元素本身的成員,示例:

<div class="demo" onclick="console.log(className)"></div>  // demo
// 等同於
<div
class="demo" onclick="console.log(this.className)"></div>

當事件內容較為複雜的時候,可將事件內容寫成函式,在on的事件屬性中執行函式

<div onclick="demo()"></div>
<script>
    function demo(){
        console.log(this)  // this指向window物件,只能通過傳參來獲取當前DOM元素
    }
</script>

通過HTML繫結事件的缺點是HTML與JavaScript程式碼耦合嚴重

方法二:在js中在DOM元素上繫結

DOM元素新增‘on’+事件名稱的屬性,this指向的是當前的DOM物件

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.onclick=function(){
        console.log(this)  // this指向的是當前的DOM物件
    }
</script>

與方法一類似,事件內容較為複雜或有多個元素需要繫結同一事件,可將事件另寫成個函式,元素只需呼叫該函式即可

<div class="demo1"></div>
<div class="demo2"></div>
<script>
    var demo1=document.querySelector(".demo1"),
        demo2=document.querySelector(".demo2")

    function demoFunc(){
        console.log(123)
    }

    demo1.onclick=demo2.onclick=demoFunc  // 123 123
</script>

這種方法的缺點是DOM物件只能繫結一個事件處理程式,後面繫結的程式會覆蓋前面繫結的程式

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.onclick=function(){
        console.log(123)  // 不會執行
    }
    demo.onclick=function(){
        console.log('abc')  // abc
    }
</script>

列印結果:abc

解除事件繫結

demo.onclick=null
方法三:使用addEventListener和attachEvent函式繫結

addEventListener函式是W3C標準規定的,IE8及IE8以下不支援
addEventListener(event,function,boolean)
event:事件名稱
function:事件處理程式的函式
boolean:false-冒泡階段呼叫程式 true-捕獲階段呼叫程式

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.addEventListener('click',function(){
        console.log(this)  // this指向當前DOM物件
    },false)
</script>

這種方法可以給DOM物件繫結多個事件處理程式,按順序執行

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.addEventListener('click',function(){
        console.log(123)
    },false)
    demo.addEventListener('click',function(){
        console.log(456)
    },false)
</script>

列印結果:123 456

繫結同一事件處理函式並且第三個引數一致,只會執行一次

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")

    function demoFunc(){
        console.log(123)
    }

    demo.addEventListener('click',demoFunc,false)
    demo.addEventListener('click',demoFunc,false)  // 只能列印一次‘123’
</script>

列印結果:123

繫結同一事件處理函式但第三個引數不一致,會執行兩次

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")

    function demoFunc(){
        console.log(123)
    }

    demo.addEventListener('click',demoFunc,false)
    demo.addEventListener('click',demoFunc,true)  // 列印兩次‘123’
</script>

列印結果:123 123

繫結相同的匿名函式,會執行兩次,兩個程式碼完全一樣的匿名函式是不相同的

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.addEventListener('click',function(){
        console.log(123)
    },false)
    demo.addEventListener('click',function(){
        console.log(123)  // 列印兩次‘123‘
    },false)
</script>

列印結果:123 123

解除事件繫結

demo.removeEventListener('click',demoFunc,false)  // 不能解除匿名函式,且第三個引數必須一致

attachEvent函式是IE特有的,IE8以下瀏覽器可以使用,可新增多個事件處理函式,只支援冒泡階段
attachEvent(‘on’+event,function)
event:事件名稱
fucntion:事件處理程式

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.attachEvent('onclick',function(){
        console.log(this)  // this指向window物件
    })
</script>

該方法同樣可以給DOM物件繫結多個事件處理程式,但是與addEventListener不同的是,attachEvent不是順序執行的,而是按相反順序執行的

<div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")
    demo.attachEvent('onclick',function(){
        console.log(123)  // 後執行
    })
    demo.attachEvent('onclick',function(){
        console.log(456)  // 先執行
    },false)
</script>

列印結果:456 123

與addEventListener一樣,同一事件處理函式只能繫結一次,相同的匿名函式可以重複繫結

    <div class="demo"></div>
<script>
    var demo=document.querySelector(".demo")

    function demofunc(){
        console.log(123)
    }

    demo.attachEvent('onclick',demofunc)
    demo.attachEvent('onclick',demofunc)  // 呼叫兩次,只會列印一次‘123’
</script>

列印結果:123

    var demo=document.querySelector(".demo")

    demo.attachEvent('onclick',function(){
        console.log(123)
    })
    demo.attachEvent('onclick',function(){
        console.log(123)  // 會列印兩個‘123’
    })

列印結果:123 123

解除事件繫結

demo.detachEvent('onclick',demofunc)  // 不能解除匿名函式

把事件繫結封裝成一個函式,相容各個瀏覽器

// 事件繫結
function addEvent(element, type, handler) {
    if(element.addEventListener){  //如果支援addEventListener
        element.addEventListener(type, handler, false);
    }else if(element.attachEvent){  //如果支援attachEvent
        element.attachEvent("on"+type, function(){
            handler.call(element);  // 將this指向當前DOM物件
        });
    }else{  //否則使用相容的onclick繫結
        element["on"+type] = handler;
    }
}
// 事件解綁
function removeEvent(element, type, handler) {
    if(element.addEventListener){
        element.removeEventListener(type, handler, false);
    }else if(element.attachEvent){
        element.detachEvent("on"+type, handler);
    }else{
        element["on"+type] = null;
    }
}

阻止預設事件
1.阻止通過on方法繫結事件的預設事件

demo.onclick=function(){
    console.log(123)
    return false
}

2.阻止通過addEventListener方法新增事件的預設事件

demo.addEventListener("click",function(e){
    var event=e||window.event
    console.log(123)
    event.preventDefault()
},false)

3.阻止通過attachEvent方法新增事件的預設事件

demo.attachEvent("onclick",function(e){
    var event=e||window.event
    console.log(123)
    event.returnValue=false
})