本篇体验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');
        };
    };

}());



当点击"开"按钮后,弹出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,鼠标事件

JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数的更多相关文章

  1. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  2. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  3. JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

    本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y) ...

  4. JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

    本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...

  5. JavaScript进阶系列02,函数作为参数以及在数组中的应用

    有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var su ...

  6. JavaScript进阶系列01,函数的声明,函数参数,函数闭包

    本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调 ...

  7. 前端入门20-JavaScript进阶之异步回调的执行时机

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  8. javascript进阶系列专题:闭包(Closure)

    在javascript中,函数可看作是一种数据,可以赋值给变量,可以嵌套在另一个函数中. var fun = function(){ console.log("平底斜"); } f ...

  9. javascript进阶系列专题:作用域与作用域链

    字面意思,作用域是指变量和函数的作用范围,换言之,作用域决定了变量和函数的可见性和有效时间.javascript作用域是用函数来区分,与其他语言的大括号不同. for (var i=0; i<5 ...

随机推荐

  1. sys和os模块

    一 sys 用于python解释器相关的操作 #!/usr/bin/env python # coding=utf-8 import time import sys def view_bar(num, ...

  2. centos7执行 wget命令: command not found的两种解决方法

    1.rpm 安装 下载wget的RPM包: http://mirrors.163.com/centos/6.8/os/x86_64/Packages/wget-1.12-8.el6.x86_64.rp ...

  3. Android 6.0 API

    Android 6.0 (M) 为用户和应用开发者提供了新功能.本文旨在介绍其中最值得关注的 API. 着手开发 要着手开发 Android 6.0 应用,您必须先获得 Android SDK,然后使 ...

  4. 前端JavaScript高级面试笔记

    一.ES6 1.模块化 ES6通过export和import实现模块化 ES6的模块化的基本规则或特点, 欢迎补充: 1:每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件 ...

  5. Ibatis.Net 表连接查询学习(五)

    IBatis.Net之多表查询 一.定制实际对应类的方式 首先配置多表的测试数据库,在之前Person表中增加一列"CountryId",新建一张Country表,两张表关系如下: ...

  6. Laravel中服务提供者和门面模式

    在laravel中,我们可能需要用到自己添加的类时,可以建立一个文件夹专门存放类文件,也可以使用laravel的服务提供者的方式来使用. 这两者其实区别不大,主要是前者使用的话,会跟业务代码产生依赖, ...

  7. Oracle学习笔记:with as子查询用法

    With as短语,也叫做子查询部分(subquery factoring),可以定义一个SQL片断,该SQL片断会被整个SQL语句用到.该语句会在真正的查询之前预先构造一个临时表,之后可以多次使用做 ...

  8. [转] React 最佳实践——那些 React 没告诉你但很重要的事

    前言:对很多 react 新手来说,网上能找到的资源大都是些简单的 tutorial ,它们能教会你如何使用 react ,但并不会告诉你怎么在实际项目中优雅的组织和编写 react 代码.用谷歌搜中 ...

  9. angular和vue双向数据绑定

    angular和vue双向数据绑定的原理(重点是vue的双向绑定) 我在整理javascript高级程序设计的笔记的时候看到面向对象设计那章,讲到对象属性分为数据属性和访问器属性,我们平时用的js对象 ...

  10. 修改MySQL中的数据

    一:insert语句 1.介绍 在执行插入语句前,需要具有执行INSERT语句的INSERT权限. 2.准备环境 3.简单insert语句 4.插入多行 在这种形式中,每行的值列表用逗号分隔. 如果为 ...