设置绑定脚本的执行顺序

时间:2016-10-04 19:17:14

标签: javascript jquery

有没有办法控制绑定到元素点击的JS脚本的执行顺序?例如,我们有两个单独的脚本,它们在同一个动作和同一个元素上触发。

第一个脚本(由网站上的脚本触发 - 我无权更改):

$('body').on('click', '#button', function1);

第二个脚本(由浏览器插件触发,我可以更改,并在其他所有内容被触发后运行):

$('body').on('click', '#button', function2);

这两个脚本是分开的(在两个不同的文件中),不能合并成这样的一个,因为我只能改变第二个:

$('body').on('click', '#button', function() {
    function1();
    function2();
});

我可以设定执行顺序吗?我可以强制最后执行一个脚本吗?

1 个答案:

答案 0 :(得分:0)

在第二个脚本中,您可以通过第一个脚本读取哪个函数与click事件绑定。然后您可以分离该处理程序并添加您自己的处理程序,如果您愿意,可以在最后一步添加原始函数的执行:



// script 1 ///////////////////////////////////////////////////////////
function f1() {
    console.log('f1: function bound by script 1');
}
$('body').on('click', '#button', f1);

// script 2 ///////////////////////////////////////////////////////////
function f2() {
    console.log('f2: my own function that should run first');
}

var original_f = $._data(document.body, 'events').click[0].handler;
$('body').off('click', '#button').on('click', '#button', function () {
    f2();
    original_f();
});

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Trigger handlers</button>
&#13;
&#13;
&#13;

这使用$._data,它不是jQuery的公共API的一部分。请参阅this answer

说明

以上解决方案假设

  1. 网站的脚本(第一个脚本)在元素body的{​​{1}}元素上使用jQuery事件委托;如下:

    #button

    请注意,还有其他方法可以附加事件处理程序,但是这个答案假设第一个脚本是这样做的(就像您在问题中提供的那样)。当然,$('body').on('click', '#button', function1); 可以是任何函数,甚至是匿名的内联函数。

  2. 您可以完全控制第二个脚本,并可以重新定义您在其中定义的点击处理程序。

  3. 您在评论中写道,您无法访问第一个脚本(function1)的功能。但请注意,如果JavaScript能够执行它,则没有理由无法通过JavaScript访问它。

    此外,由于您通知第一个脚本使用jQuery附加其处理程序,jQuery也知道它是哪个函数并且可以访问它(当发生单击事件时它还能如何执行它?)。

    我上面提供的解决方案实际上要求jQuery为您提供该函数的引用。然后你可以像jQuery在发生点击事件时那样执行它。

    测试处理程序的存在

    为了验证第一个脚本确实以这种方式设置了处理程序:

    function1

    ...而且仍然存在,您可以使用以下脚本进行调试:

    &#13;
    &#13;
    $('body').on('click', '#button', function1);
    
    &#13;
    // script 1 -- you don't need to enter this, it is for this snippet to work with.
    function f1() {
        console.log('f1: function bound by script 1');
    }
    $('body').on('click', '#button', f1);
    
    // script 2 -- your code ///////////////////////////////////////////////////////////
    
    var click_handlers = $._data(document.body, 'events').click;
    console.log('Info on BODY click handlers that have been set via jQuery:\n',
                 JSON.stringify(click_handlers, null, 2));
    
    console.log('First click handler is this function:\n', click_handlers[0].handler);
    &#13;
    &#13;
    &#13;