JavaScript進階系列05,事件的執行時機, 使用addEventListener為元素同時註冊多個事件,事件引數

Darren Ji發表於2014-10-04

本篇體驗JavaScript事件的基本面,包括:

 

事件必須在頁面元素載入之後起效
點選事件的一個簡單例子
為元素註冊多個點選事件
獲取事件引數

跨瀏覽器事件處理


□ 事件必須在頁面元素載入之後起效

 

有這樣一段簡單的程式碼:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style>
        #box {
            background: blue;
            height: 100px;
            width: 100px;
            left: 50px;
            top: 50px;
        }
    </style>
</head>
<body>
    <div id="box"></div>
</body>

 

現在,我們想給id為box的div新增事件,建立一個script.js檔案。

(function() {
    var ele = document.getElementById("box");
    ele.onclick = function() {
        this.style.background = "red";
    };
}());

是一個匿名函式,只要被引用,自動執行。

 

如果把script.js放在head區域。

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    ......
    <script src="script.js"></script>
</head>

點選頁面藍色區域會報錯:Cannot set property 'onclick' of null

 

找不到需要實施onclick事件的元素。如果我們把script.js放在body區域底部,又會怎樣呢?

<body>
    <div id="box"></div>
    <script src="script.js"></script>
</body>

點選頁面藍色區域背景色變成紅色。

 

由此可以看出:事件必須在頁面元素載入完畢之後才可以實施。

 

以上,通過把JavaScript程式碼放在需要實施事件元素的下方,保證了先載入元素,再執行事件,這很好。而實際上,通過window的onload方法也可以保證所有頁面元素載入完畢再執行事件。

 

修改script.js的程式碼為:

(function () {
    window.onload = function() {
        var ele = document.getElementById("box");
        ele.onclick = function () {
            this.style.background = "red";
        };
    };
}());

把script.js程式碼放在head部分。點選頁面藍色區域背景色變成紅色。

 

□ 點選事件的一個簡單例子

 

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style>
        .on {
            background-color: white;
            color: black;
        }
        .off {
            background-color: black;
            color: white;
        }
    </style>
    <script src="script.js"></script>
</head>
<body class="on">
    <h1>Hello World</h1>
    <p>歡度國慶</p>
    <button id="open">開</button>
    <button id="close">關</button>
</body>

 

script.js的程式碼為:

(function () {
    window.onload = function() {
        var openBtn = document.getElementById("open");
        var closeBtn = document.getElementById("close");
        openBtn.onclick = function() {
            document.body.className = "on";
        };
        closeBtn.onclick = function() {
            document.body.className = "off";
        };
    };

 

一切執行正常。但,如果我們在script.js中給開按鈕再註冊一個事件。

(function () {
    window.onload = function() {
        var openBtn = document.getElementById("open");
        var closeBtn = document.getElementById("close");
        openBtn.onclick = function() {
            document.body.className = "on";
        };
        closeBtn.onclick = function() {
            document.body.className = "off";
        };
        openBtn.onclick = function() {
            alert('hello');
        };
    };
}());

2
當點選"開"按鈕後,彈出alert。由此可以看出:每次只能為元素註冊一個onclick事件。

 

□ 為元素註冊多個點選事件

 

使用addEventListener方法,可以為元素同時註冊多個點選事件。

 

修改script.js程式碼如下:

(function () {
    window.onload = function() {
        var openBtn = document.getElementById("open");
        var closeBtn = document.getElementById("close");
        var open = function() {
            document.body.className = "on";
        };
        var close = function() {
            document.body.className = "off";
        };
        //第三個引數設定成false,表示允許事件冒泡
        openBtn.addEventListener("click", open, false);
        openBtn.addEventListener("click", function() { alert('hello'); }, false);
        closeBtn.addEventListener("click", close, false);
    };
}());

 

當然,也可以移除註冊的事件。

        //移除EventListner事件
        openBtn.removeEventListener("click", open, false);

 

注意:在IE8下沒有addEventListner,應該使用attachEvent。

openBtn.attachEvent("onclick", function(evt)){
    alert(evt.srcElement);//相當於target屬性
    document.body.className = "on";
};

○ attachEvent只有2個引數
○ 事件名稱是onclick,而不是click
○ event.srcElement相當於event.target

 

如果在IE8下注銷事件。

openBtn.detachEvent("onclick",函式名稱);

 

□ 獲取事件引數

 

在每次發生事件的時候,所有的事件引數資訊都被放在了一個event變數中。修改script.js程式碼為:

(function () {
    window.onload = function() {
        var openBtn = document.getElementById("open");
        var closeBtn = document.getElementById("close");
        var open = function (e) {
            alert(e.type + " " + e.target);
            document.body.className = "on";
        };
        var close = function (e) {
            alert(e.type + " " + e.target);
            document.body.className = "off";
        };
        //第三個引數設定成false,表示允許事件冒泡
        openBtn.addEventListener("click", open, false);
        closeBtn.addEventListener("click", close, false);
    };
}());    

可見,函式的事件引數在大多數情況下被省略了,如果想獲取事件資訊,這個event引數還是很有用的。   

 

□ 跨瀏覽器事件處理

 

正因為,在不同的瀏覽器下事件處理方式不同,比如在chrome下接收addEventListener方法,而在IE8下接收attachEven方法,我們有必要針對跨瀏覽器提供一個通用的事件處理機制。

 

建立eventUtiltiy.js檔案。

var eventUtility = {
    addEvent: function(ele, type, fn) {
        if (typeof addEventListener !== "undefined") {
            ele.addEventListener(type, fn, false);
        } else if (typeof attachEvent !== "undefined") { //比如在IE8下
            ele.attachEvent("on" + type, fn);
        } else {
            //獲取屬性通過obj.屬性名稱,等同於obj[屬性名稱]
            //執行事件通過obj.事件名稱,等同於obj[事件名稱]
            ele["on" + type] = fn;
        }
    },
    removeEvent: function(ele, type, fn) {
        if (typeof removeEventListener !== "undefined") {
            ele.removeEventListener(type, fn, false);
        } else if (typeof detachEvent !== "undefined") {
            ele.detachEvent("on" + type, fn);
        } else {
            ele["on" + type] = null;
        }
    },
    getTarget: function(event) {
        if (typeof event.target !== "undefined") {
            return event.target;
        } else {
            return event.srcElement;
        }
    },
    preventDefault: function(event) {
        if (typeof event.preventDefault !== "undefined") {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    getCharCode: function(event) {
        if (typeof event.charCode === "number") {
            return event.charCode;
        } else {
            return event.keyCode;
        }
    }
};

 

頁面部分。

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <style>
        .on {
            background-color: white;
            color: black;
        }
        .off {
            background-color: black;
            color: white;
        }
    </style>
    
</head>
<body class="on">
    <h1>Hello World</h1>
    <p>歡度國慶</p>
    <button id="open">開</button>
    <button id="close">關</button>
    <script src="eventUtility.js"></script>
    <script src="script.js"></script>
    
</body>

 

script.js部分。

(function () {
        var openBtn = document.getElementById("open");
        var closeBtn = document.getElementById("close");
        var open = function () {
            //alert(e.type + " " + e.target);
            document.body.className = "on";
        };
        var close = function () {
            //alert(e.type + " " + e.target);
            document.body.className = "off";
        };
        
        eventUtility.addEvent(openBtn, "click", open);
        eventUtility.addEvent(closeBtn, "click", close);
}());

 

 

“JavaScript進階系列”包括:

JavaScript進階系列01,函式的宣告,函式引數,函式閉包

JavaScript進階系列02,函式作為引數以及在陣列中的應用

JavaScript進階系列03,通過硬編碼、工廠模式、建構函式建立JavaScript物件

JavaScript進階系列04,函式引數個數不確定情況下的解決方案

JavaScript進階系列05,事件的執行時機, 使用addEventListener為元素同時註冊多個事件,事件引數

JavaScript進階系列06,事件委託

JavaScript進階系列07,滑鼠事件

相關文章