JavaScript常见事件处理程序实例总结


Posted in Javascript onJanuary 05, 2019

本文实例总结了JavaScript常见事件处理程序。分享给大家供大家参考,具体如下:

事件指的是使用者或者浏览器自身执行的某种动作(比如点击事件)。响应这些事件的函数就叫做事件处理程序(或者叫事件监听器)。事件处理程序的名字以“on”为前缀,比如 click 事件的事件处理程序就是 onclick。

1 HTML 事件处理程序

如果某个元素支持某个事件,那么它都有一个与相应的事件处理程序同名的 HTML 属性,我们可以通过这个属性来指定 JS:

<input type="button" value="点我" onclick="alert('点击过咯')"/>

因为这里的脚本是嵌入在 HTML 元素的属性中,所以使用了单引号!

也可以调用在页面的其他地方定义的脚本:

<input type="button" value="Click me" onclick="showMessage()">
<script type="text/javascript">
  function showMessage() {
    console.log("Hello World!");
  }
</script>

事件处理程序的代码在执行时,可以访问到全局作用域中的任何代码!

这样指定的事件处理程序,会创建一个封装着元素属性值的函数,它有一个局部变量 event,就是事件对象:

<input type="button" value="点我" onclick="alert(event.type)"/>

通过 event 变量,可以直接访问事件对象。在这个函数内部,this 值等于事件的目标元素:

<input type="button" value="点我" onclick="alert(this.value)"/>

可以通过这个动态创建的函数,来扩展它的作用域。在这个函数内部,可以访问 document 以及该元素本身的成员,这个函数是像这样使用 with 来扩展作用域的:

function(){
  with(document){
    with(this){
      //元素属性值
    }
  }
}

所以,在事件处理程序中,要访问自己的属性就变得很容易啦 O(∩_∩)O~:

<!-- 输出 “点我” -->
<input type="button" value="点我" onclick="alert(value)"/>

如果当前元素是一个表单输入元素,则作用域中还会包含访问表单元素(父元素)的入口,所以这个函数应该是这样的:

function(){
  with(document){
    with(this.form){
       with(this){
        //元素属性值
       }
    }
  }
}

这样事件处理程序就无需引用表单元素,就可以直接访问到表单中的其他字段啦O(∩_∩)O~:

<form method="post">
  <input type="text" name="username" value="">
  <input type="button" value="Echo Usernmame" onclick="console.log(username.value);">
</form>

在 HTML 中直接指定事件处理程序会有这些缺点:

  • 时差问题——假设函数是定义在页面最底部,如果用户在页面还未解析到这个函数时,就点击了按钮,就会引发错误。所以很多 HTML 事件处理程序都会被封装在 try-catch 块中:
<input type="button" value="点我" onclick="try{alert(value);} catch(ex){}"/>
  • 扩展事件处理程序的作用域链,在不同的浏览器中结果可能会不同。
  • HTML 与 JavaScript 代码紧密耦合。要修改事件处理程序,就需要修改两个地方,所以很多开发人员转而使用 JavaScript 来指定事件处理程序。

2 DOM0 级事件处理程序

它是通过将一个函数赋值给事件处理程序的属性,来指定事件处理程序的。要使用这种方法,必须先取得一个要操作的对象的引用。

每个元素(包括 window 和 document) 都有自己的事件处理程序属性,它们通常是小写,比如 onclick。将属性的值设置为函数,就指定了事件处理程序。

DOM0 级事件处理程序是元素的方法,它是在元素的作用域内运行的,因此程序中的 this 引用的是当前元素:

<button id="myBtn">点我</button>
<script type="text/javascript">
  var btn = document.getElementById("myBtn");
  btn.onclick = function () {
    console.log(this.id);//myBtn
  }
</script>

可以通过 this 访问元素的任何属性和方法。DOM0 级事件处理程序会在事件流的冒泡阶段被处理。

也可以像这样删除这样指定的事件处理程序:

btn.onclick = null; //删除指定的事件处理程序

注意: 如果使用的是 HTML 指定的事件处理程序,那么 onclick 属性的值就是一个包含着在同名 HTML 特性中指定的代码函数。将相应的属性设置为 null,也可以删除以这种方式指定的事件处理程序。

3 DOM2 级事件处理程序

  • addEventListener():指定事件处理程序。
  • removeEventListener():删除事件处理程序。

所有的 DOM 节点都包含这两个方法。它们都接受 3 个参数:要处理的事件名、事件处理程序函数、布尔值。最后一个参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。

DOM2 级事件处理程序可以很方便地添加多个事件处理程序:

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function () {
  console.log(this.id);
}, false);
btn.addEventListener("click", function () {
  console.log("Hello world!");
}, false);

这些事件处理程序会按照添加它们的顺序依序触发。

通过 addEventListener() 添加的事件处理程序只能使用 removeEventListener() 移除!移除时传入的参数必须与添加时的参数相同。这也就意味着通过 addEventListener() 添加的匿名函数将无法被移除:

var handler = function () {
  console.log("Hi deniro");
};
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);//移除成功

大多数情况下,都是将事件处理程序添加到事件流的冒泡阶段,这样可以最大限度地兼容浏览器。所以如果不是特别需要,请不要在事件捕获阶段注册事件处理程序。

注意: IE9、Firefox、Safari、Chrome 和 Opera 支持 DOM2 级事件处理程序。

4 IE 事件处理程序

IE 实现了与 DOM 类似的方法:attachEvent()detachEvent()。它们接受两个参数:事件处理程序名称和事件处理程序函数。因为 IE8 及早期版本只支持事件冒泡,所以使用 attachEvent() 添加的事件处理程序会被添加到冒泡阶段。

这样为按钮添加一个事件处理程序:

var btn = document.getElementById("myBtn");
  btn.attachEvent("onclick", function () {
});

IE 的 attachEvent() 与 DOM0 级方法的区别是事件处理程序的作用域不同。 DOM0 级方法中,事件处理程序会在其所属元素的作用域内运行;而使用 attachEvent() ,事件处理程序会在全局作用域中运行,所以 this 等于 window:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function () {
  console.log("Clicked");
  console.log(this === window);//true;this 为全局作用域
});

也可以为一个元素添加多个事件处理程序:

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function () {
  console.log("Clicked");
  console.log(this === window);//true;this 为全局作用域
});
//IE10 中多个事件是按照事件定义的顺序执行
btn.attachEvent("onclick", function () {
  console.log("Hello world!");
});

IE8 及之前的版本,是以添加它们的相反顺序进行,IE9 修复了这个问题。

可以通过 detachEvent() 来移除添加的事件处理程序,但必须提供相同的参数。所以它也不能移除之前通过匿名函数添加的事件处理程序。只要能够将对相同函数的引用作为参数,就可以移除添加的事件处理程序咯:

<button id="myBtn">点我</button>
<script type="text/javascript">
  var btn = document.getElementById("myBtn");
  var handler = function () {
    console.log("Clicked");
  }
  btn.attachEvent("onclick", handler);
  btn.detachEvent("onclick", handler);
</script>

注意: IE 和 Opera 支持 IE 事件处理程序。

5 跨浏览器的事件处理程序

只要恰当地运用能力检测,就能写出跨浏览器的事件处理程序。

var EventUtil = {
  /**
   * 添加事件
   * @param element 要操作的元素
   * @param type 事件名称
   * @param handler 事件处理函数
   */
  addHandler: function (element, type, handler) {
    if (element.addEventListener) {
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
      element.attachEvent("on" + type, handler);
    } else {
      element["on" + type] = handler;
    }
  },
  /**
   * 移除事件
   * @param element 要操作的元素
   * @param type 事件名称
   * @param handler 事件处理函数
   */
  removeHandler: function (element, type, handler) {
    if (element.removeEventListener) {
      element.removeEventListener(type, handler, false);
    } else if (element.detachEvent) {
      element.detachEvent("on" + type, handler);
    } else {
      element["on" + type] = null;
    }
  }
}

这样使用:

<button id="myBtn">点我</button>
<script type="text/javascript" src="EventUtil.js"/>
<script type="text/javascript">
  var btn = document.getElementById("myBtn");
  var handler = function () {
    console.log("Clicked");
  }
  EventUtil.addHandler(btn, "click", handler);
  EventUtil.removeHandler(btn, "click", handler);
</script>

还有一点,DOM0 级对每一个事件只支持一个事件处理程序,好在现在只支持 DOM0 级事件处理程序的浏览器几乎已经没有咯,所以不用担心啦 O(∩_∩)O~

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
Html中JS脚本执行顺序简单举例说明
Jun 19 Javascript
使用JS进行目录上传(相当于批量上传)
Dec 05 Javascript
jQuery ajax(复习)—Baidu ajax request分离版
Jan 24 Javascript
Node.js模拟浏览器文件上传示例
Mar 26 Javascript
jquery插件pagination实现无刷新ajax分页
Sep 30 Javascript
原生js实现移动端瀑布流式代码示例
Dec 18 Javascript
Javascript必知必会(四)js类型转换
Jun 08 Javascript
返回函数的JavaScript函数
Jun 14 Javascript
ionic+AngularJs实现获取验证码倒计时按钮
Apr 22 Javascript
JavaScript定义及输出螺旋矩阵的方法详解
Dec 01 Javascript
小程序红包雨的实现示例
Feb 19 Javascript
vue spa应用中的路由缓存问题与解决方案
May 31 Javascript
JavaScript代码调试方法实例小结
Jan 05 #Javascript
JavaScript实现连连看连线算法
Jan 05 #Javascript
JavaScript错误处理操作实例详解
Jan 04 #Javascript
JSON基本语法及与JavaScript的异同实例分析
Jan 04 #Javascript
JavaScript解析及序列化JSON的方法实例分析
Jan 04 #Javascript
Node.js操作系统OS模块用法分析
Jan 04 #Javascript
Node.js console控制台简单用法分析
Jan 04 #Javascript
You might like
一个简单php扩展介绍与开发教程
2010/08/19 PHP
PHP日期处理函数 整型日期格式
2011/01/12 PHP
PHP学习散记_编码(json_encode 中文不显示)
2011/11/10 PHP
在PHP中设置、使用、删除Cookie的解决方法
2013/05/06 PHP
php stream_get_meta_data返回值
2013/09/29 PHP
laravel框架数据库操作、查询构建器、Eloquent ORM操作实例分析
2019/12/20 PHP
论坛里点击别人帖子下面的回复,回复标题变成“回复 24# 的帖子”
2009/06/14 Javascript
jquery获取input表单值的代码
2010/04/19 Javascript
解析js中获得父窗口链接getParent方法以及各种打开窗口的方法
2013/06/19 Javascript
JS截取字符串常用方法详细整理
2013/10/28 Javascript
Javascript中常见的校验如域名、手机、邮箱等等
2014/01/02 Javascript
JQuery实现的购物车功能(可以减少或者添加商品并自动计算价格)
2015/01/13 Javascript
使用 TypeScript 重新编写的 JavaScript 坦克大战游戏代码
2015/04/07 Javascript
JS实现跟随鼠标的链接文字提示框效果
2015/08/06 Javascript
JavaScript实现自动弹出窗口并自动关闭窗口的方法
2015/08/06 Javascript
javascript数据类型验证方法
2015/12/31 Javascript
只需五句话搞定JavaScript作用域(经典)
2016/07/26 Javascript
js中less常用的方法小结
2017/08/09 Javascript
vue.js 双层嵌套for遍历的方法详解, 类似php foreach()
2018/09/07 Javascript
Vue框架TypeScript装饰器使用指南小结
2019/02/18 Javascript
create-react-app中添加less支持的实现
2019/11/15 Javascript
python字符串加密解密的三种方法分享(base64 win32com)
2014/01/19 Python
python实现根据ip地址反向查找主机名称的方法
2015/04/29 Python
Python聚类算法之DBSACN实例分析
2015/11/20 Python
使用Nginx+uWsgi实现Python的Django框架站点动静分离
2016/03/21 Python
使用django-guardian实现django-admin的行级权限控制的方法
2018/10/30 Python
Python面向对象之类的封装操作示例
2019/06/08 Python
Python爬虫 bilibili视频弹幕提取过程详解
2019/07/31 Python
pytorch .detach() .detach_() 和 .data用于切断反向传播的实现
2019/12/27 Python
纯css3实现的鼠标悬停动画按钮
2014/12/23 HTML / CSS
HTML5 Web存储方式的localStorage和sessionStorage进行数据本地存储案例应用
2012/12/09 HTML / CSS
关于HTML5+ API plusready的兼容问题
2020/11/20 HTML / CSS
澳大利亚相机之家:Camera House
2017/11/30 全球购物
瀑布模型都有哪些优缺点
2014/06/23 面试题
开业庆典答谢词
2014/01/18 职场文书
幼儿园春季开学寄语
2014/04/03 职场文书