【问题标题】:jQuery .on() not bound when script inserted into the DOM将脚本插入 DOM 时,jQuery .on() 未绑定
【发布时间】:2012-05-28 17:11:51
【问题描述】:

我有一个包含自定义 jQuery 事件处理程序的远程 javascript 文件。当它作为 <script src='...'></script> 元素插入 DOM 时,自定义事件处理程序未注册。

但是,如果我添加与直接 JS (<script>...</script>) 完全相同的脚本,则会注册事件处理程序,并且一切都会按预期执行。

当脚本作为远程文件插入时,为什么事件处理程序没有绑定到 jQuery 中?

示例

远程文件,包含自定义事件处理程序:

console.log('Before custom event handler');
$('button').on('customEvent', function(){
    console.log('customEvent Caught');
});

https://gist.github.com/2767385

将脚本插入 DOM 的 (non-working) javascript:

var scriptNode = document.createElement('script');
    scriptNode.src = 'https://gist.github.com/raw/2767385/b9ddea612ff60b334bd2430e59903174e527a3b5/gistfile1.js';
document.body.appendChild(scriptNode);

将脚本作为内联插入 DOM 的(工作替代)javascript:

var scriptText = "console.log('Before custom event handler'); $('button').on('customEvent', function(){ console.log('customEvent Caught'); });",
    scriptNode = document.createElement('script');
scriptNode.appendChild(document.createTextNode(scriptText));
document.body.appendChild(scriptNode);

触发事件:

$('button').triggerHandler('customEvent');

JS被正确读取,handler被正确执行。

JSFiddles

远程文件 - 非工作示例:http://jsfiddle.net/3CfFM/3/
使用文本 - 工作替代:http://jsfiddle.net/3CfFM/2/

发生了什么?

当脚本作为远程文件插入时,为什么事件处理程序没有绑定到 jQuery 中?

【问题讨论】:

    标签: javascript events jquery dom-manipulation


    【解决方案1】:

    你错了。当与远程脚本一起使用时,事件处理程序正在被绑定;只是需要更长的时间。浏览器需要在绑定处理程序之前发出 HTTP 请求。这意味着您使用triggerHandler('customEvent') 触发的原始​​事件不会被捕获,因为它的冒泡和捕获已经完成。

    如果你稍等片刻,然后再次点击按钮,你会看到事件处理程序确实已经被绑定了。您还可以通过延迟您的 triggerHandler 调用直到脚本加载来看到这一点:

    $('button').click(function() {
        var scriptNode = document.createElement('script');
        scriptNode.src = 'https://gist.github.com/raw/2767385/897cffca74411dbb542c0713bacb5a4048d6708b/gistfile1.js';
        scriptNode.onload = function() {
            $('button').triggerHandler('customEvent');
        };
        document.body.appendChild(scriptNode);
    });
    

    http://jsfiddle.net/3CfFM/4/

    【讨论】:

    • 啊哈!除了等待脚本下载之外,我的 jsfiddle 和您的 jsfiddle 之间的一个重要区别是:我调用的是 $(this).triggerHandler(...),而您(更正确地)调用的是 $('button').triggerHandler(...)
    • 不,没有区别。在您的脚本中,this 是按钮。在我的,因为我有一个额外的事件处理程序(onload 方法)this 将是scriptNode 元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-02
    • 1970-01-01
    • 2019-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多