【问题标题】:How to make a Javascript event handler to execute first?如何使 Javascript 事件处理程序首先执行?
【发布时间】:2016-08-27 11:06:31
【问题描述】:

我有一个使用 jQuery & parsley 插件进行表单验证和提交的页面。下面是表单的事件处理程序,

$('#formid').parsley().on('form:submit', function(event) {
    //handle form submit
});

我有另一个纯 JavaScript 侦听器函数要在提交表单时执行。下面是代码sn-p,

document.getElementById("formid").addEventListener("submit",function(e){
   //Some code to be executed after form submit
});

我要求不要将 jQuery 用于上述功能。

现在的问题是,parsley 正在使用 event.stopImmediatePropagation(); 阻止事件流向下游

因此,第二个事件处理程序没有得到执行。有没有办法让我的纯 javascript 处理程序首先执行?我遇到了this jQuery 解决方案来绑定事件处理程序。但我需要纯 JavaScript 解决方案。任何帮助是极大的赞赏。

更新: 这是JSFiddle 解决我的问题。

【问题讨论】:

  • 您问题的全部内容必须您的问题中,而不仅仅是链接。使用 Stack Snippets(<> 工具栏按钮)代替 jsFiddle,将演示问题所需的完整代码放入可运行的现场演示中。
  • 我将您的小提琴作为 Stack Snippet 复制到您的问题中,发现您已经绊倒了 jsFiddle 将所有内容包装在 window.onload = function() { /*your code here*/}; 包装器中的令人惊讶的默认值 .如果您使用选项来关闭该包装器(这是一个非常愚蠢的默认设置),那么您在我的回答中遇到的问题就会消失。
  • 你是对的!谢谢你。如果我更改为 onDOMReady,该代码将起作用。但就我而言,我无法控制这一点,因为我的代码位于链接到 html 页面标题的外部 javascript 文件中。欧芹 jQuery 代码位于 html 正文中的脚本标记中。所以这里无法控制顺序。
  • 将引用外部文件的script标签放在head中通常不是一个好主意(除非你使用asyncdefer),你不能移动它吗?
  • 我的代码是一个外部 JS 文件,在页面的 head 标签中带有 async 属性。不幸的是,我无法改变这一点。我的代码必须在外部文件中。

标签: javascript jquery dom-events parsley.js


【解决方案1】:

唯一的方法是确保将addEventListener 处理程序添加到 jQuery 处理程序之前。 jQuery 将使用addEventListener 为事件添加它的处理程序(此时它将为该元素上的该事件的所有处理程序使用单个处理程序),并且由于使用addEventListener 添加的处理程序按照它们添加的顺序进行处理,您的非 jQuery 处理程序将首先由浏览器执行。

例子:

// The first addEventListener handler -- does get called
document.getElementById("the-button").addEventListener("click", function () {
    console.log("first addEventListener handler called");
}, false);

// The jQuery handler that stops immediate propagation
$("#the-button").on("click", function (e) {
    console.log("jQuery handler called");
    e.stopImmediatePropagation();
});

// The second addEventListener handler -- doesn't get called
document.getElementById("the-button").addEventListener("click", function () {
    console.log("this message won't be output");
}, false);
<input type="button" id="the-button" value="Click Me">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【讨论】:

  • 感谢您的解决方案。但这对我不起作用。我在带有欧芹的听众之前添加了我的听众,但仍然控制到了欧芹。关于我应该寻找的点有什么想法吗?
  • @SathishJayaram:你能为此创建一个minimal reproducible example 吗?我发现非常很难相信您在addEventListener 注册first 的处理程序会在 jQuery 处理程序之后触发。如果它是 attachEvent(旧的 Microsoft 事物),那将是不同的(它的工作方式相反),但 addEventListener 绝对可以如上所述工作。
  • @Crowder 用小提琴链接更新了我的问题。请看一看。
【解决方案2】:

是的,你可以这样做。使用 Boolean true 作为第三个参数来执行 addEventListener 函数,如下所示。它在事件的捕获阶段绑定处理程序。更多关于事件的捕获和冒泡阶段see

document.getElementById("formid").addEventListener("submit",function(e){
   //Some code to be executed after form submit
}, true);

【讨论】:

    【解决方案3】:

    希望这会有所帮助

    第一种方式

    我不知道这是否可行,请尝试刷新您的传播事件:

    var refEvent = event.originalEvent;
    refEvent.cancelBubble = false;
    refEvent.defaultPrevented = false;
    refEvent.returnValue = true;
    refEvent.timeStamp = (new Date()).getTime();
    
    if (event.target.dispatchEvent){
        event.target.dispatchEvent(refEvent);
    } else if (event.target.fireEvent) {
        event.target.fireEvent(refEvent);
    }
    

    然后你可以在你的处理程序执行后再次停止传播,这次再次添加event.stopPropagation();到你的处理程序

    第二种方式

    //监听器

    var stoped = false;
    if(stoped){
        event.stopPropagation();
    }
    

    //处理程序

    var stoped = true
    

    来源:How to undo event.stopPropagation in jQuery?

    【讨论】:

    • 一个痛点是页面是外部的。所以我不应该修改 parsley 函数,第二种方法不适合我的情况。第一种方式我不太明白,refEvent指向什么?
    猜你喜欢
    • 2011-10-27
    • 1970-01-01
    • 2011-03-22
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 2013-06-09
    • 1970-01-01
    相关资源
    最近更新 更多