0

0

javascript中事件的解析(详细)

不言

不言

发布时间:2018-09-10 16:28:48

|

2321人浏览过

|

来源于php中文网

原创

本篇文章给大家带来的内容是关于javascript中事件的解析(详细),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

JavaScript、浏览器、事件之间的关系

JavaScript程序采用了异步事件驱动编程(Event-driven programming)模型,维基百科对它的解释是:

事件驱动程序设计(Event-driven programming)是一种电脑程序设计模型。这种模型的程序运行流程是由用户的动作(如鼠标的按键,键盘的按键动作)或者是由其他程序的消息来决定的。相对于批处理程序设计(batch programming)而言,程序运行的流程是由程序员来决定。批量的程序设计在初级程序设计教学课程上是一种方式。然而,事件驱动程序设计这种设计模型是在交互程序(Interactive program)的情况下孕育而生的

简言之,在web前端编程里面JavaScript通过浏览器提供的事件模型API和用户交互,接收用户的输入。

由于用户的行为是不确定的。这种场景是传统的同步编程模型没法解决的,因为你不可能等用户操作完了才执行后面的代码。所以在javascript中使用了异步事件,也就是说:js中的事件都是异步执行的

立即学习Java免费学习笔记(深入)”;

事件驱动程序模型基本的实现原理基本上都是使用 事件循环(Event Loop),这部分内容涉及浏览器事件模型、回调原理。

JavaScript DOM、BOM模型中,同样异步的还有setTimeout,XMLHTTPRequest这类API并不是JavaScript语言本身就有的。

事件绑定的方法

事件绑定有3种方法:

行内绑定

直接在DOM元素上通过设置on + eventType绑定事件处理程序。例如:

点击我

这种方法有两个缺点:

  1. 事件处理程序和HTML结构混杂在一起,不符合MVX的规范。为了让内容、表现和行为分开,我们应该避免这种写法。

  2. 这样写的代码判断具有全局作用域,可能会产生命名冲突,导致不可预见的严重的后果。

在DOM元素上直接重写事件回调函数

使用DOM Element上面的on + eventType属性 API

var el = getElementById('button');  //button是一个

这种方法也有一个缺点:后绑定的函数会覆盖之前的函数。比如我们注册一个window.onload事件,可能会覆盖某个库中已有的事件函数。当然,这个可以有解决方法:

function addEvent(element, EventName, fun) {   //EventName = 'on' + eventType
    var oldFun = element[EventName];
    if (typeof oldFun !== 'function') {
        element[EventName] = fun;
    } else {
        element[EventName] = function() {
            oldFun();
            fun();
        };
    }
}

addEvent(window, "onload", function() { alert('onload 1') });
addEvent(window, "onload", function() { alert('onload 2') });

当然,一般情况下使用DOM Ready就可以了,因为JavaScript在DOM加载完就可以执行了

标准绑定方法

标准的绑定方法有两种,addEventListener和attachEvent前者是标准浏览器支持的API,后者是IE8以下浏览器支持的API:

//例如给一个button注册click事件
var el = getElementById('button');  //button是一个

需要注意的是:

  1. addEventLister的第一个参数事件类型是不加on前缀的,而attachEvent中需要加on前缀。

  2. addEventLister中的事件回调函数中的this指向事件元素target本身,而attachEvent中的事件回调函数的this指向的是window。

  3. addEventLister有第三个参数,true表示事件工作在捕获阶段,false为冒泡阶段(默认值:false)。而attachEvent只能工作在冒泡阶段。

在chrome中运行如下代码:

click me

点击后弹出顺序是: 3 -> 4 -> 5 -> 1

这里第4行代码覆盖了行内的onclick定义,如果注释了这一行,输入顺序为: 2 -> 4 -> 5 -> 1,而addEventListener之间不会发生覆盖。

解除事件绑定

对于上述的前二个方法,解除事件绑定只需要将对应的事件函数设为null,就可以了:

var el = document.getElementById('button');
el.onclick = null;

对于上述第三种方法使用removeListen()方法即可,在IE8中,对应使用detachEvent()。注意,他们和上面的注册方法一一对应,不能混用。

//这是一段错误代码,不能实现事件移除

//建立一个事件
var el = document.getElementById('button');  //button是一个

以上的错误在于事件函数这样定义时,虽然看着完全一样,但在内存中地址不一样。这样一来,电脑不会认为解除的和绑定的是同一个函数,自然也就不会正确解除。应该这样写:

亿众购物系统
亿众购物系统

一套设计完善、高效的web商城解决方案,独有SQL注入防范、对非法操作者锁定IP及记录功能,完整详细的记录了非法操作情况,管理员可以随时查看网站安全日志以及解除系统自动锁定的IP等前台简介:  1)系统为会员制购物,无限会员级别。  2)会员自动升级、相应级别所享有的折扣不同。  3)产品可在缺货时自动隐藏。  4)自动统计所有分类中商品数量,并在商品分类后面显示。  5)邮件列表功能,可在线订阅

下载
//建立一个事件
var el = document.getElementById('button');  //button是一个

事件的捕获与冒泡

之前说addEventListener函数的第三个参数表示捕获和冒泡,这个是一个重点!

我自己描述一下他们的定义就是:

冒泡:在一个元素上触发的某一事件,会在这个元素的父辈元素上会依次由内向外触发该事件,直到window元素。

捕获:在一个元素上触发的某一事件,这个元素的每一层的所有子元素上触发该事件,并逐层向内,直到所有元素不再有子元素。

如下图(注:图片来自百度搜索)

1299470535-5ac2e1ad61621_articlex.jpg

事件间回到函数参数是一个事件对象,它里面包括许多事件属性和方法,比如,我们可以用以下方式阻止冒泡和默认事件:

//该例子只写了handler函数
function handler(event) {
    event = event || window.event;
    //阻止冒泡
    if (event.stopPropagation) {
        event.stopPropagation();      //标准方法
    } else {
        event.cancelBubble = true;    // IE8
    }
    //组织默认事件
    if (event.perventDefault) {
        event.perventDefault();      //标准方法
    } else {
        event.returnValue = false;    // IE8
    }
}

其次,普通注册事件只能阻止默认事件,不能阻止冒泡

element = document.getElemenById("submit");
element.onclick = function(e){
    /*...*/
    return false;    //通过返回false,阻止冒泡
}

事件对象

事件函数中有一个参数是事件对象,它包含了事件发生的所有信息,比如键盘时间会包括点击了什么按键,包括什么组合键等等,而鼠标事件会包括一系列屏幕中的各种坐标和点击类型,甚至拖拽等等。当然,它里面也会包括很多DOM信息,比如点击了什么元素,拖拽进入了什么元素,事件的当前状态等等。

这里关于事件兼容性有必要强调一下:

document.addEventListener('click', function(event) {
    event = event || window.event;   //该对象是注册在window上的
    console.log(event);   //可以输出事件对象看一看, 属性很多很多
    var target = event.target || event.srcElement;  //前者是标准事件目标,后者是IE的事件目标
},false);

关于鼠标事件坐标的问题,可以看另一篇博客:元素和鼠标事件的距离属性

事件触发

除了用户操作以外,我们也可以写代码主动触发一个事件,以ele元素的click事件为例:

ele.click();   //触发ele元素上的单击事件

事件代理

有时候我们需要给不存在的的一段DOM元素绑定事件,比如用户动态添加的元素,或者一段 Ajax 请求完成后渲染的DOM节点。一般绑定事件的逻辑会在渲染前执行,但绑定的时候找不到元素所以并不能成功。

为了解决这个问题,我们通常使用事件代理/委托(Event Delegation)。而且通常来说使用 事件代理的性能会比单独绑定事件高很多,我们来看个例子。

  • 传统注册事件方法,当内容很多时效率低,不支持动态添加元素

  • item-1
  • item-2
  • item-3
  • item-4
  • item-5
  • 事件委托注册方法,不论内容有多少都只注册1次,支持动态添加元素:

  • item-1
  • item-2
  • item-3
  • item-4
  • item-5

事件封装

很明显,处理浏览器兼容太麻烦了,所以这里把js中的事件注册相关函数封装一下,作为整理。

//均采用冒泡事件模型
var myEventUtil={
    //添加事件函数
    addEvent: function(ele, event, func){
        var target = event.target || event.srcElement;
        if(ele.addEventListener){
            ele.addEventListener(event, func, false);
        } else if(ele.attachEvent) {
            ele.attachEvent('on' + event, func);   //func中this是window
        } else {
            ele['on' + event] = func;    //会发生覆盖
        }
    },
    //删除事件函数
    delEvent:function(ele, event, func) {
        if(ele.removeEventListener){
            ele.removeEventListener(event, func, false);
        } else if(ele.detachEvent) {
            ele.detachEvent('on' + event, func);
        } else {
            ele['on' + event] = null;
        }
    },
    //获取触发事件的源DOM元素
    getSrcElement: function(event){
        return event.target || event.srcElement;
    },
    //获取事件类型
    getType: function(event){
        return event.type;
    },
    //获取事件
    getEvent:function(event){
        return event || window.event;
    },
    //阻止事件冒泡
    stopPropagation: function(event) {
        if(event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBuble = false;
        }
    },
    //禁用默认行为
    preventDefault: function(event){
        if(event.preventDefault){
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    }
};

jQuery中的事件

需要注意的是: JQuery中的事件都工作在冒泡阶段,且只能工作在冒泡阶段

注册、解除事件

  • 方法一:

//不会发生覆盖,但不利于解除,不能动态操作事件

$("#button").click(function(){   //注册一个click事件,当然可以用其他事件名的函数注册其他事件
  console.log("clicked");
});
  • 方法二:

//不会发生覆盖,利于解除,不能动态操作事件

//注册一个事件
$("#button").bind("click", function() {    //注册一个click事件,当然可以用其他事件名的函数注册其他事件
  console.log("clicked");
});
//当然还可以这样写,给事件指定命名空间
$(document).bind('click.handler1', function() { console.log(1);})
$(document).bind('click.handler2', function() { console.log(2);})

//解除一个事件
$("#button").unbind(".handler1");    //解除元素上所以handler1命名空间中的事件
$("#button").unbind('click.handler2');   // 解除元素上的click.handler2事件
$("#button").unbind('click');            // 解除元素上所有点击事件
$("#button").unbind()                    // 解除元素上所有事件

//bind()方法还介受3个参数形式,这里就不赘述了,感兴趣可以自己看看相关资料。
  • 方法三:

//不会发生覆盖,但不利于解除,能动态操作事件,依赖于事件冒泡

//注册事件
$(document).delegate(".item", "click", function(){console.log(this.innerHTML);});   //第一个是选择器, 第二个是事件类型, 第三个是事件函数

//移除事件
$(document).undelegate(".item", "click", handler);  //移除元素上指定事件
$(document).undelegate(".item", "click");  //移除元素上所有click事件
$(document).undelegate(".item");  //移除元素上所有事件
  • 方法四:

//不会发生覆盖,但不利于解除,能动态操作事件,不依赖于事件冒泡

//注册事件
#(".item").live("click", function(){console.log(this.innerHTML);})  //第一参数是事件类型, 第二参数是事件函数

//移除事件
$(".item").die("click", handler);  //移除元素上指定click事件
$(".item").die("click");  //移除元素上所有click事件
  • 两个简化方法:

//hover方法
$("#button").hover(function(){
        //鼠标移入时的动作,不冒泡
    }, function(){
        //鼠标移出时的动作,不冒泡
});

//toggle方法
$("#button").toggle(function(){
        //第一次点击时的动作
    }, function(){
        //第二次点击时的动作
}, .../*可以放多个函数,依次循环响应*/);

事件触发

//不能触发addEventListener和attachEvent
//主动触发一个事件
$("#button").trigger("click");   //触发所有click事件
$("#button").trigger("click.handler1");   //触发所有click.handler1事件
$("#button").trigger(".handler1");   //触发所有handler1命名空间的事件
$("#button").trigger("click!");   //触发所有没有命名空间的click事件
$("#button").trigger(event);   //在该元素上触发和事件event一样的事件
$("#button").trigger({type:"click", sync: true});   //触发click事件,同步

相关推荐:

带你快速理解javascript中的事件模型

JavaScript事件类型中UI事件详解_javascript技巧

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
jquery插件有哪些
jquery插件有哪些

jquery插件有jQuery UI、jQuery Validate、jQuery DataTables、jQuery Slick、jQuery LazyLoad、jQuery Countdown、jQuery Lightbox、jQuery FullCalendar、jQuery Chosen和jQuery EasyUI等。本专题为大家提供jquery插件相关的文章、下载、课程内容,供大家免费下载体验。

150

2023.09.12

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

jquery删除元素的方法
jquery删除元素的方法

jquery可以通过.remove() 方法、 .detach() 方法、.empty() 方法、.unwrap() 方法、.replaceWith() 方法、.html('') 方法和.hide() 方法来删除元素。更多关于jquery相关的问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

394

2023.11.10

jQuery hover()方法的使用
jQuery hover()方法的使用

hover()是jQuery中一个常用的方法,它用于绑定两个事件处理函数,这两个函数将在鼠标指针进入和离开匹配的元素时执行。想了解更多hover()的相关内容,可以阅读本专题下面的文章。

504

2023.12.04

jquery实现分页方法
jquery实现分页方法

在jQuery中实现分页可以使用插件或者自定义实现。想了解更多jquery分页的相关内容,可以阅读本专题下面的文章。

182

2023.12.06

jquery中隐藏元素是什么
jquery中隐藏元素是什么

jquery中隐藏元素是非常重要的一个概念,在使用jquery隐藏元素之前,需要先了解css样式中关于元素隐藏的属性,比如display、visibility、opacity等属性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

120

2024.02.23

jquery中什么是高亮显示
jquery中什么是高亮显示

jquery中高亮显示是指对页面搜索关键词时进行高亮显示,其实现办法:1、先获取要高亮显示的行,获取搜索的内容,再遍历整行内容,最后添加高亮颜色;2、使用“jquery highlight”高亮插件。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

176

2024.02.23

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

38

2026.01.13

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

158

2026.01.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.2万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 2.5万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号