JavaScript事件处理是发生在程序流程内部还是外部?

11

这个问题与Javascript事件处理和流程控制相关,但它比那个问题更进一步。仍未回答的问题是:当触发事件并将控制权返回给浏览器时,浏览器是否会决定先处理其他事件(由其他脚本或用户操作触发)(A)或始终直接处理我的事件(B)?

Javascript事件处理是在程序流程内(B)还是外部(A)? 这个问题很重要,因为如果是(B),您可以依赖于在触发事件和事件处理程序之间没有任何更改,而(A)则不提供任何保证。

我的第一个猜测是(B),否则如何使用stopPropagation()和preventDefault()呢?但重新考虑后,并没有硬性证据。

这个问题的一个现实例子。我正在修改一个所见即所得的富文本编辑器(hallo),我希望它具备以下规格:

  • 单击可编辑文本(#txt)将激活编辑器,并在单击#txt之外时将其停用。 hallo使用#txt上的blur和focus事件来实现此功能。
  • 激活编辑器会打开工具栏,工具栏上的mousedown(但不是按钮)将设置一个标志,以防止#txt上的模糊事件停用编辑器。 工具栏将使#text重新获得焦点。
  • 在工具栏按钮上按下鼠标也应该防止停用编辑器,但它应该等待点击事件,执行其操作,然后返回焦点到#txt。 一些操作是立即执行的(加粗或斜体),而另一些需要额外的用户输入(从下拉列表中选择)。
  • 其中一些按钮会打开对话框。
  • ...我希望所有这些元素(编辑器、工具栏、对话框)都是模块化的且易于扩展。

现在,在大多数情况下,当你关闭一个对话框时,你希望焦点返回到 #txt。但是,在打开对话框并单击页面上的其他地方的情况下,编辑器将关闭并调用工具栏,包括要关闭的对话框。在这种情况下,如果对话框返回焦点到编辑器,它会再次激活编辑器。

就我现在的理解而言,事件处理顺序至少是可确定的。不可能出现某些事件延迟处理而其他事件先被处理的情况。这就是所谓的“同步”。当然,像加载文件这样的事件是例外。

从组件程序的角度来看,比如对话框,情况可能相当不可预测。它可以绑定一个处理程序到打开事件,然后调用 dialog("open"),但在调用和处理程序之间任何事情都可能发生,即使只是因为编辑器有一个在同一事件上的处理程序。

因此,我的结论是1)是可预测的,但 2)需要一个复杂的体系结构来实现这一点。


在您的 openDialog()doThing() 函数中添加几个 console.log() 语句进行测试这不是很简单吗? - lanzz
@lanzz:一个(A)的单一例子肯定能证明(A),但到目前为止我只找到了(B),或者说,到目前为止我没有捕获到第一个和第二个之间的其他事件处理程序。不幸的是,这并不能证明什么。 - Carlo Roosen
openDialog 的代码是什么?你没有在同一节点集上注册两个 click 事件,所以我不认为你会得到 (B) - Ja͢ck
我的问题更为随意的表述是:当你吸引了浏览器的注意力,你是否通过调用事件来放弃它? - Carlo Roosen
1
@Carlo,jQuery并不透明地使用本地事件模型,它有一个内部模型,并钩住了本地模型。您可以在jQuery源代码中清楚地看到这一点。其中一个主要原因是,该事件模型不能保证执行顺序,但jQuery可以,因为它维护自己的已注册处理程序数组。然而,这并不改变问题的答案。 - davin
显示剩余4条评论
1个回答

4
通常事件模型是同步和可重入的,这意味着如果一个事件处理程序引起另一个事件,第二个事件将会同步执行,并且只有在完成后,第一个事件才会继续执行。
这似乎是您试图描述的情况,如果是这样的话,则(B)是保证的。
相关来源:http://www.w3.org/TR/DOM-Level-3-Events/#event-flow

我相信仅仅因为事件模型是同步和可重入的,(A)就是正确的。对话框上的打开事件可以被许多事件处理程序处理,这些处理程序又可以调用其他在程序返回之前处理的事件。所以在打开对话框和它的处理程序之间,任何事情都可能发生 (?). 除了根据你的说法,jQuery有自己的模型。 - Carlo Roosen
困难在于“同步和可重入”是从浏览器的角度来看的。从程序的角度来看,情况就不同了。老实说,我无法理解它。 - Carlo Roosen
1
很明显,因为浏览器不知道哪个处理程序应该调用哪个其他处理程序,所以它不会首先调用一个处理程序,因为另一个处理程序引起了某些事件。这将过于复杂,我看不出这有什么意义。在你的特定示例中,由于jQuery处理事件的方式,这也没有意义,尽管那是另一个问题。 - davin
1
同步和可重入仅是表示它是阻塞和嵌套的一种方式。因此,如果事件A有处理程序A1、A2、... An,并且Ak导致事件B,B具有处理程序B1、... Bm,则执行顺序如下:A1、A2、...、Ak、B1、B2、...、Bm、A(k+1)、... An。这意味着可能存在无限嵌套,因此如果B的处理程序导致C,则递归应用相同的逻辑。最后,请注意,在纯事件模型中,执行处理程序的顺序(如我之前提到的)不能保证。 - davin
1
@CarloRoosen,关于顺序,是的,那正是我所指的。 - davin
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接