2015-07-19 57 views
1

我正在通过ajax加载HTML部分。该部分通过在现有节点上使用innerHTML附加到DOM。未直接加载脚本

的部分包含在底部的一些脚本标签,是这样的:

<script src="/Scripts/Griffin.Editor.js" type="text/javascript"></script> 
<script type="text/javascript"> 
      marked.setOptions({ 
       renderer: new marked.Renderer(), 
       gfm: true, 
       tables: true, 
       breaks: false, 
       pedantic: false, 
       sanitize: true, 
       smartLists: true, 
       smartypants: false 
      }); 
      var textParser = { 
       parse: function (text) { 
        return marked(text); 
       } 
      } 
      var prismHighlighter = { 
       highlight: function (blockElements, inlineElements) { 
        blockElements.forEach(function(item) { 
         Prism.highlightElement(item); 
        }); 

       } 
      }; 
      var editor = new Griffin.Editor('editor', textParser); 
      editor.syntaxHighlighter = prismHighlighter; 
      editor.preview(); 
</script> 

但是,作为脚本标签不执行,我遍历加载部分,以确定所有的脚本标记。然后,我在DOM中创建新的脚本节点并将它们附加到HEAD

喜欢的东西:

var scripts = viewElem.getElementsByTagName('script'); 
for (let i = 0; i < len; i++) { 
    var scriptTag = scripts[0]; 
    let node = document.createElement('script'); 
    if (scriptTag.src && scriptTag.src.length > 0) { 
     node.src = scriptTag.src; 
     node.type = scriptTag.type; 
    } else { 
     node.text = scriptTag.text; 
     node.type = scriptTag.type; 
     //had eval here before (instead of attaching the embedded script to the HEAD). 
    } 
    document.head.appendChild(node); 
    scriptTag.parentNode.remove(scriptTag); 
} 

从我的理解调用嵌入脚本之前,浏览器应该加载引用的脚本。然而,我不是这种情况,因为JS控制台抱怨没有找到依赖脚本中定义的对象。

如果我使用一个计时器并评估嵌入式脚本中的一切工作。但这似乎是一个丑陋的解决方法,我真的很想了解加载行为背后的机制(即为什么当部分附加到DOM时不执行脚本,以及为什么在将节点添加到HEAD标签)。

+0

是否包含脚本文件撰写或其他内联唯一的代码?你也立即删除脚本,也许还有一些需要 – mplungjan

+0

可能是一些脚本文件依赖于其他脚本文件加载的问题。你应该检查这个答案。 [链接](http://stackoverflow.com/a/29250976/1577396) –

+0

@mplungjan:我添加了真正的脚本 – jgauffin

回答

0

从我遇到的情况来看,您不能立即在Ajax响应中执行JavaScript。原因是您试图在另一个JavaScript函数中执行JavaScript。所以浏览器不知道在这个场景中使用哪个执行上下文。

我会推荐使用像你提到的延期执行。除此之外,您需要让浏览器先解释Ajax响应。例如:

$.get('url', function (html) { 
    // html = "<script>function myTest() { console.log('here'); }</script>" 
    $('#result').html(html); 
    // Now that the DOM has had time to parse the response we can do: 
    myTest(); 
}); 

注意它是Ajax回调调用立即响应函数不响应执行本身。希望这可以帮助。

+0

脚本是部分返回的html(在你的例子中是'html' var的一部分) – jgauffin

0

我发现一个really great article深入解释脚本如何加载到浏览器中。

实质上,当您动态地包含脚本时,您无法确定默认情况下的执行顺序。要确定您需要执行以下操作之一的订单:

a。 b。使用async=false(如果支持)
b。使用readyState(例如< 10)
c。使用defer属性。

尝试按顺序使用上述功能以确保。

但是,即使您完成了所有这些操作,如果将嵌入的脚本(脚本标记中的代码)与引用的脚本(使用src属性)混合在一起,仍然会受到干扰。

问题是嵌入式脚本会直接运行,即使之前添加了引用脚本标记。为了解决这个问题,您需要将嵌入式脚本推入队列并挂接所有引用脚本的load事件。

一旦所有引用的脚本都触发了load甚至你可以自由地调用嵌入的脚本(通过添加脚本标签的元素或eval他们text属性)。

来源:http://blog.gauffin.org/2015/07/embedded-script-tags-in-content-loaded-through-ajax-and-execute-the-script-tags-dynamically/