当前位置: 首页 > 科技观察

JavaScript浏览器事件分析

时间:2023-03-21 12:48:20 科技观察

JavaScript程序采用异步事件驱动编程(Event-drivenprogramming)模型,维基百科对它的解释是:事件驱动编程(英文:Event-drivenprogramming)是一种计算机编程模型。该模型的程序运行过程是由用户动作(如鼠标按键、键盘按键动作)或来自其他程序的消息决定的。与批处理编程(batchprogramming)相比,程序运行的过程是由程序员决定的。批处理编程是初级编程教学课程中的一种方式。然而,事件驱动编程的设计模型是在交互式程序(Interactiveprogram)的情况下诞生的。简而言之,在Web前端编程中,JavaScript通过浏览器提供的事件模型API与用户进行交互,接收到用户的输入,由于用户的行为是不确定的,也就是说不知道用户什么时候点击和卷轴。这种场景是传统的同步编程模型无法解决的,因为你不能等到用户完成操作之后再执行下面的代码。例如,如果我们在Python中调用方法raw_input()来接收用户输入,那么终端将一直等待用户的输入。,直到输入完成后才会执行下面的代码逻辑。但是在下面的NodeJS代码中,接收用户输入的方法process.stdin.read在事件中被调用。下面的代码不会被阻塞(blocked)'usestrict';process.stdin.on('readable',()=>{varchunk=process.stdin.read();if(chunk!==null){process.stdout.write(`Asyncoutputdata:${chunk}`);}});process.stdin.on('end',()=>{process.stdout.write('end');});console.log('Willnotbeblocked');事件驱动程序模型的基本实现原理基本上都是使用事件循环(EventLoop)。这部分内容涉及浏览器事件模型和回调原理。有兴趣的可以看链接里的视频,了解自己需要什么可见客户端JavaScript中的setTimeout、XMLHTTPRequest等API,JavaScript语言本身是不存在的。它是JavaScript的宿主环境(浏览器是客户端JavaScript)。同样,DOM、BOM、EventAPI都是浏览器提供的事件绑定方法。DOM元素内联绑定是直接在DOM元素上通过设置on+eventType来绑定事件处理器clickme这种绑定方式是最原始的有两个缺点:1.事件处理程序和HTML结构混合在一起。在结构、风格和性能分离的早期,它被认为是最佳实践。现在好像在很多MVX框架中,事件绑定和DOM结构是一起处理的,这样维护起来似乎更方便。(无需来回切换HTML和JavaScript文件),也符合可预见的规则2Namespaceconflicts因为onclick中JavaScript代码片段的执行环境是全局作用域。但是,JavaScript语言中并没有相关的命名空间特性。所以很容易造成命名空间冲突。如果非要用这种方法来绑定事件,那只能用对象做一些封装了。旧的绑定方法在DOM元素上使用on+eventType属性APIclickme这种方法也有一个缺点,因为属性赋值会覆盖原来的价值。因此,不能绑定多个事件处理程序。如果我们想注册多个onload事件处理程序,我们必须封装一个方法来防止这种情况发生。下面的例子可以解决这个问题。注意这只是一个例子,很少会用到一个生产环境。一般可以使用DOMReady,因为JavaScript的执行通常不需要等到所有页面资源都加载完毕,DOM加载完毕。Modern/standardbindingmethods标准的绑定方法有两种,addEventListener和attachEvent,前者是标准的浏览器支持的API,后者是IE8以下浏览器支持的API。通常我们需要做一个兼容包上面例子的效果和IE8以下的标准浏览器不一样,问题是addEventListener中事件回调函数中的this指向元素(target)本身,而attachEvent指向window。为了修复这个问题上面的attachEvent可以稍微调整一下,保持和addEventListener一样,但是在这种情况下注册的handler是一个匿名函数,不能被移除!当以上情况同时出现时,就比较有意思了.可以试试下面的代码输出clickme正确的结果应该是3,4,5,1,根据结果我们可以得出以下结论:链接上的href伪javascript协议相当于在浏览器地址栏中执行了一段JavaScript代码。如果链接是这种格式,当链接被点击时,相当于在JavaScript脚本行中执行了事件绑定,在元素上调用onclick绑定事件会覆盖jQuery的使用(内部使用标准事件注册API)绑定多个事件处理器事件冒泡大多数事件会沿着事件触发的目标元素向上传播例如:body>div>p>span如果他们都注册了点击事件,那么在span元素上触发点击事件后,p、div、body各自的点击事件也会依次触发。可以停止事件冒泡。以下函数关闭停止事件冒泡的方法:事件对象在标准浏览器中,当调用事件处理程序时,事件对象将通过参数传递给handler,IE8及以下浏览器可以通过全局window.event访问Event对象。比如我们要获取当前点击的DOMElement事件代理有时候我们需要绑定一个事件到一个不存在的DOM元素上(可能在未来),比如Ajax后渲染的DOM节点请求完成绑定事件。一般绑定的逻辑会在渲染之前执行。绑定的时候找不到元素,所以不会成功。当然,你也可以把绑定事件的代码放在Ajax请求之后。这在一些事件逻辑简单的应用中是可以的,但是会增加数据渲染逻辑和事件处理之间的逻辑耦合。一旦事件处理程序过多,我们通常建议将事件逻辑与其他代码逻辑分离,以便于维护。为了解决这个问题,我们通常使用事件代理/委托(EventDelegate)。而且一般来说,使用事件代理的性能会比单独绑定事件高很多。让我们看一个例子item1item2item3item4item5如果ul中的html是ajax异步插入的,通常我们的做法就是在插入完成后遍历每一个li绑定事件handler然后我们使用事件代理将事件绑定到ul元素。我们知道许多事件可以沿着DOM树传播到所有父元素。我们只需要判断目标元素是否是我们要绑定的真实元素很明显,使用了事件代理之后,代码变少了,逻辑也清晰了。关键是以前需要N次的绑定操作,现在在jQuery中只需要一次事件绑定。以jQuery1.6.4为例,jQuery提供了很多事件绑定的API。比如:delegate()、bind()、click()、hover()、one()、live(),这些方法其实都是一些别名,核心是调用jQuery底层事件的jQuery.event.add方法.它的实现也是上面提到的addEventListener和attachEvent这两个API。这些API主要是为了方便绑定事件的各种场景,内部处理兼容性问题。另一个有用的地方是事件命名空间。例如:两个弹出层都绑定到文档关闭点击事件,但是如果你只想解绑其中一个。这是使用名称空间的最佳时机。您可以尝试这个小示例EventBinding自定义事件和发布/订阅设计模式自定义事件是发布/订阅在设计模式下的一种实现。发布者和订阅者是松耦合的,不需要关心彼此的存在。这是NCMaster的一种实现。在实际使用中,主要用于异步操作比较多,不同系统之间进行消息通信的场景。之前的文章中有一些例子。事件驱动编程设计事件介绍JavaScript中的自定义事件