为啥jQuery的ajax会自动运行脚本?

Posted

技术标签:

【中文标题】为啥jQuery的ajax会自动运行脚本?【英文标题】:Why does jQuery's ajax automatically run scripts?为什么jQuery的ajax会自动运行脚本? 【发布时间】:2013-11-21 05:51:01 【问题描述】:

我最近注意到,如果在将 jQuery 注入内部 iframe 后立即调用 jQuery ajax,则 jQuery 会失去其功能 - 例如 jQuery(..).dialog()、.draggable 和任何其他插件。如果 ajax 调用被注释掉,则 jQuery 工作正常。这是一个已知的错误,还是我做错了什么?这个问题可以看这个文件,和jQuery在同一个目录下:

<html>
<head>
    <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
    <script src="jquery.js"></script>
    <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
</head>
<body>

Try and <button id="btn">load</button>
<iframe width=300 height=300></iframe>

<script>
"use strict";
jQuery('#btn').click(function()
    var $ = jQuery;
    console.log(typeof jQuery('iframe').dialog);
    var doc = jQuery('iframe')[0].contentDocument;
    function insertscript(src) 
        var newscript = doc.createElement('script');
        newscript.setAttribute('src',src);
        doc.documentElement.appendChild(newscript);
    
    insertscript('jquery.js');

    //This breaks the jQuery plugins:
    var test = $.get('jquery.js',function()
        //Now we know jQuery should be in the frame.
    );

    //So does this:
    //jQuery.ajax(url:'http://192.168.1.17/wordpress/wp-includes/js/jquery/jquery.js',cache:true,processData:false);

    console.log(typeof jQuery('iframe').dialog);
    window.setTimeout(function()
        //jQuery is no longer the original jQuery object. Note the cached reference $().dialog does exist though.
        console.log('after awhile... dialog is ' + typeof jQuery('iframe').dialog);
    ,3000)
    //jQuery.ajax(url:jqurl,cache:true,processData:false);
);
</script>
</body></html>

这是问题的最小示例,确保 iframe 已加载某个 jQuery.js(然后 ajax 应该有缓存的脚本),然后再将一些其他内容添加到 iframe。

点击加载,一段时间后,控制台日志将显示“一段时间后...对话框未定义” - 仅在使用 ajax 时。

更新:看起来$.get('jquery.js') 实际运行脚本。 $.get('alert.js') 显示警报,当 alert.js 具有警报功能时。 (对于 jQuery,重新定义全局 jQuery 引用。)为什么 jQuery 的 ajax 会有这种行为?所有 ajax 实现都会发生这种情况吗?

【问题讨论】:

您是在说将脚本应用于动态内容...?还是别的什么? 如果您可以将其转换为 jsfiddle 中的简化测试用例或其他内容,则更容易测试错误 另外,你为什么要对jquery.js?进行ajax调用 我试过 jsfiddle 但它似乎需要同域。我正在加载 ajax,所以我知道以后插入插件脚本会起作用,因为我有 jQuery。 如果你再次加载 jQuery....将清除任何绑定到初始 jQuery 对象的现有插件。覆盖初始的 jQuery 对象。应该从解释情况开始。 【参考方案1】:

正如之前有人回答的那样(谁的回答被删除了?),jQuery ajax 会根据您请求的内容类型自动选择要执行的操作。 (不幸的是,记录不足的功能)。加载外部 js 不仅会在浏览器获取脚本后返回,还会运行脚本。

当你稍后重新包含 jQuery 时,它会重写 window.jQuery 对象,因此删除 jQuery.prototype.dialog 等。

Firefox 的 .watch 函数在这种情况下会很有帮助,可以查看在哪里重新定义了某些内容。例如,这将为您提供任何重新定义 jQuery 的堆栈跟踪:

window.watch('jQuery',function()  console.trace()  )

【讨论】:

以上是关于为啥jQuery的ajax会自动运行脚本?的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 自动完成 + AngularJS 的问题

jquery ajax 脚本运行成功但导致错误

自动化脚本运行稳定性(一)——脚本健壮性

首次加载页面时,Jquery UI 自动完成功能不起作用

php为啥会自动停止执行

jQuery——事件和AJAX