0

我正在尝试首先创建一个iframe然后将其注入 jQuery 库,然后提醒说 jQuery 已加载。

jQuery 库按预期插入到iframe头部,jQuery 上的警报加载到正文中。

问题是,它没有显示警报,而是说jQuery is not defined.

任何人都可以提出任何建议吗?

这是代码

<!doctype html>
<html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
        <title>iFrame Test</title>
    </head>
    <body>
        <script>
            var insertScript = function(src){
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.async = false;
                script.src = src;
                $('iframe').contents().find('head')[0].appendChild(script);
            }

            var insertScriptContent = function(code){
                var script = document.createElement('script');
                script.type = 'text/javascript';
                script.async = false;
                script.innerHTML  = code;
                $('iframe').contents().find('body')[0].appendChild(script);
            }

            $(function(){
                $('iframe').load(function(){
                    var contents = $('iframe').contents();
                    insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');
                    insertScriptContent('jQuery(function(){ alert("loaded"); });');
                });
            });
        </script>

        <div class="output">
            <iframe></iframe>
        </div>
    </body>
</html>
4

1 回答 1

2

您正在异步加载 jQuery(尽管有script.async=false),然后在此之后立即加载警报脚本。该脚本运行时尚未加载 jQuery,因此您将获得未定义的jQuery引用。

作为一个快速修复,我添加了一个setInterval()等待直到jQuery被定义。我还进行了以下其他更改:

  • 删除了script.async = false;这两个地方,因为它没有任何好处。
  • 去掉了$('iframe').load()包装。当我测试您的代码时,该包装器中的回调函数根本不会被调用。这并不奇怪,因为此时没有任何内容被加载到 iframe 中。
  • document.createElement()更改了您用来使用 iframe 文档(iframedoc在我的版本中调用)的两个地方。使用它可以正常工作document,但我更愿意在它们将被加载到的文档下创建这些脚本。
  • 将 的两个实例更改...find(something)[0].appendChild();为更简单的...find(something).append();.

这是工作代码:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();
            var iframedoc = $contents[0];

            var insertScript = function(src) {
                var script = iframedoc.createElement('script');
                script.type = 'text/javascript';
                script.src = src;
                $('iframe').contents().find('head').append(script);
            }

            var insertScriptContent = function(code) {
                var script = iframedoc.createElement('script');
                script.type = 'text/javascript';
                script.innerHTML = code;
                $('iframe').contents().find('body').append(script);
            }

            insertScript('https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js');

            insertScriptContent(
                'var timer = setInterval( function() {' +
                    'if( typeof jQuery == "undefined" ) return;' +
                    'clearInterval( timer );' +
                    'jQuery(function(){ alert("loaded"); });' +
                '}, 50 )'
            );

        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

这对于第一次通过来说很好,但是有一种更简单的方法可以做到这一点。我尝试用 jQuery 代码替换这两个脚本函数,所以这是另一个工作版本:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();

            $contents.find('head').append(
                '<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"><\/script>'
            );

            $contents.find('body').append(
                '<script>' +
                    'jQuery(function(){ alert("loaded"); });' +
                '<\/script>'
            );

        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

奇怪的是,这个没有setInterval()计时器就可以正常工作,所以我把那个代码拿出来了。我不确定为什么会这样——这不是一种令人欣慰的感觉——但它在我测试过的浏览器中似乎是一致的。

最后,这是一个无效的实验。过去,我使用过document.write()针对 iframe 的效果。所以我想我会尝试:

<!doctype html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript">
</script>

    <title>iFrame Test</title>
</head>

<body>
    <script type="text/javascript">

        $(function() {
            var $contents = $('iframe').contents();
            var iframedoc = $contents[0];

            iframedoc.write(
                '<!doctype html>',
                '<html>',
                '<head>',
                    '<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.js"><\/script>',
                '</head>',
                '<body>',
                    '<script>',
                        'debugger;',
                        'jQuery( function(){ alert("loaded"); } );',
                    '<\/script>',
                '</body>',
                '</html>'
            );
        });
    </script>

    <div class="output">
        <iframe></iframe>
    </div>
</body>
</html>

这个版本确实将 jQuery 和内联脚本加载到 iframe 中,并在内jQuery()联脚本中执行调用。但它从不调用带有alert()in 的回调函数。这实际上与我正在做的事情有关,所以我明天可能会再看一遍,但同时我留下了实验代码,以防你好奇。我将其更改为在 iframe 中使用未压缩的 jQuery 以便于调试,并debugger;在其中留下了一条语句。

于 2013-04-17T06:18:09.827 回答