了解JavaScript事件注册的几种方式

boyanx5个月前技术教程25

JS事件类型可以分为三种:

鼠标事件,由某个鼠标动作引发。常用的有click、mouseover、mouseout、mousedown、mouseup、dbclick、mousemove等;

键盘事件,由某个键盘动作引发。常用的有keydown、keypress、keyup;

接口事件,由用户行为的结果引起的事件,而非由用户行为直接引起的;如按下表单的submit按钮,会引起submit事件,由用户点击a链接时会要开新页面并释放当前页,些时会引起unload事件等,常用的有blur、focus、change、contextmenu、load、unload、readystatechange、reset、submit、resize、scroll等。

一旦我们决定使用何种事件来完成交互时所需要做的事情时,就需要注册事件处理程序,事件注册方式有两种模型:

传统模型

行内作为属性。即直接在HTML元素通过添加属性形式来注册,优点是所有浏览器都兼容,缺点是维护难,违背了结构与行为相分离的WEB标准原则,所以不提倡,代码像这样:

<a href="index.html">do</a>

<p>test</p>

值得注意的是大小写的问题,由于HTML对大小写不敏感,所以在过去编写这些事件时按惯例采用的驼峰格式像这样onClick、onMouseOver,但是值得注意的是作为元素的属性写在HTML里这样没有问题,但是如果是在在js环境里这样是不行的,因为js对大小敏感。

结构与行为分离

结构与行为分离的方式是遵循了WEB标准,要想分离必须设置关联钩子,像这样:

<a href="index.html" id="link">do</a>

<p id="test">test</p>

<script>

var link = document.getElementById('link'),

test = document.getElementById('test');

link.onclick = doThis;

test.onclick = doThat;

function doThis(){...}

function doThat(){...}

</script>

需要注意的是这里的函数名后面没有加(),加了表示立即执行,有时候我们想在页面加载完就立即执行一次那就需要加()。还有就是大小写的问题,之前也提到过了,这里的事件名字要小写像这样onclick,否则无法识别。当然还支持另一种形式即匿名函数,像这样:

var link = document.getElementById('link'),

test = document.getElementById('test');

link.onclick = function(){...};

test.onclick = function(){...};

虽然我们大部分时候都是用的这种传统方式,而且也不会发生什么错误,但它还是有它的缺点,那就是覆盖问题,按照代码从上往下的执行顺序,如果一个对象注册了相同的几个事件,那么最后的一个会把前面定义的事件全部覆盖,建议在项目完全由我们自己掌控的情况下可以使用些方法,无兼容性,且简单直观。如需要解决覆盖问题请看下面的高级事件注册模型。

高级模型

此模型主要用来有效解决覆盖问题,但是它有一个兼容性问题,即IE浏览器与其它WEB标准浏览器的事件注册方法不一样,幸运的是,解决这个兼容性问题并不难,我们先看看W3C(WEB标准浏览器阵容支持)和微软(IE系列阵容支持)所支持的高级事件处理程序方法:

obj.addEventListener('click', doThis, false); //添加

obj.removeEventListener('click', doThis, false); //移除

//Microsoft

obj.attachEvent('onclick', doThis); //添加

obj.detachEvent('onclick', doThis); //移除

上面的代码我们可以看出,W3C提供的addEventListener和removeEventListener方法有三个参数:

第一个是事件名称,它是字符串类型的;

第二个是事件发生后要执行的函数,通常我们是不需要立即执行的,所以不带();

第三个参数接收的是一个布尔值,指定事件传递的方式,false表示冒泡,true表示事件捕获。

Microsoft提供的attachEvent和detachEvent方法有两个参数:

第一参数是事件名称,它是字符串类型的,但和W3C不同的是微软它的事件名称需要加上on,和普通模型一样的;

第二参数是事件发生后要执行的函数,和W3C一样

我们可以写个两个通用函数来解决兼容性问题,像这样:

注册事件

addEventSimple(obj, evt, fn, bool){

//对象检测,通常都是将W3C制定的方法判断在前面,因为那些暂时不支持的浏览器或许哪一天就跟随标准了,放在前面这也是提升性能的小技巧

if(obj.addEventListener){

bool = bool || false;

obj.addEventListener(evt, fn, bool);

}else if(obj.attachEvent){

obj.attachEvent('on'+evt, fn);

}

}

//移移注册事件

removeEventSimple(obj, evt, fn, bool){

if(obj.removeEventListener){

bool = bool || false;

obj.removeEventListener(evt, fn, bool);

}else if(obj.detachEvent){

obj.detachEvent('on'+evt, fn);

}

}

addEventSimple接受四个参数,其中前三个是必须的,第四个是可选的

obj指定注册事件的对象,数据类型为Object;

evt指定事件名称,数据类型为String;

fn指定事件发生后要执行的函数;

bool指定事件传递的类型,数据类型为Boolean;

接下来我们就可以这样使用了:

<a href="index.html" id="link">do</a>

<p id="test">test</p>

<script>

var link = document.getElementById('link'),

test = document.getElementById('test');

addEventSimple(link, 'click', doThis);

addEventSimple(link, 'click', doThat);

addEventSimple(test, 'click', doThis);

addEventSimple(test, 'click', doThat);

function doThis(){...}

function doThat(){...}

</script>

这样就不会覆盖了,虽然事件注册高级模型,看似很牛B,但也有它的缺点,除了刚才所说的兼容性问题,还有一个就是它无法移除对象上同一个注册事件绑定的所有执行函数。如果需要移除就必须要知道对象事件注册绑定的执行函数名称如上面的doThis、doThat。而传统模型是可能的:obj.onclick = null。

文/丁向明

做一个有博客的web前端自媒体人,专注web前端开发,关注用户体验,加我qq/微信交流:6135833

http://dingxiangming.com

标签: iscroll.js

相关文章

登录人人都是产品经理即可获得以下权益

在 2025 年,AI 爬虫领域迎来了全新变革。本文聚焦于 2025AI 爬虫最佳实践,深入实战演示如何运用 Deepseek、Crawl4ai 以及 Playwright MCP 这三大工具组合,实...

利用 Fluid 自制 Mac 版 Overcast 应用

我喜爱收听播客,健身、上/下班途中,工作中,甚至是忙着做家务时。大多数情况下我会用 Marco Arment开发的Overcast(Freemium)在 iPhone 上收听,这是我目前最喜爱的 Po...

作弊技术2——网站劫持(网站劫持软件)

很多站长朋友都知道网站劫持,但是还是有人不知道什么是网站劫持,网站劫持是什么,下面就由小编介绍一下网站劫持的基本内容。一、什么是网站劫持网站劫持就是指在打开一个网址的时候,出现了一个不属于网站范围的广...

有时你并不需要 JavaScript!(有时候 你需要的就只是20秒毫无理智的勇气)

通过阅读本文,希望你能意识到在项目中可以减少JavaScript的使用。原文链接:https://www.htmhell.dev/adventcalendar/2023/2/未经允许,禁止转载!作者...

小巧 Vue 页面滚动进度条组件ScrollProgress

今天给大家分享一个轻量级Vue.js全屏滚动进度条组件VueScrollProgress。vue-scroll-progress 一款基于vue.js构建的页面滚动进度条组件,非常小巧,GZIP压缩后...

轻量级 React.js 虚拟美化滚动条组件RScroll

前几天有给大家分享一个Vue自定义滚动条组件VScroll。今天再分享一个最新开发的React PC端模拟滚动条组件RScroll。vue+pc桌面端模拟滚动条组件VScrollrscroll 一款基...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。