使用jQuery从HTML文本查询脚本元素

bkc*_*rad 5 ajax jquery

我通过加载页面$.ajax()并插入部分结果到页面的相应部分:

$.ajax({
  url: '/whole_page.html',
  success: function (data, status, xhr) {
    $result = $(xhr.responseText);
    $('#menu').html($('#menu', $result).html());
    $('#content').html($('#content', $result).html());
  }
});
Run Code Online (Sandbox Code Playgroud)

像魅力一样,但我遇到了问题.

现在我的页面包含一些特定于页面的JS,在获取和插入结果时必须执行这些JS.据我所知,script如果你从HTML文本构造一个jQuery对象并对它进行查询,jQuery将不会返回元素(我已经做了一个小提示来演示).所以,我无法通过jQuery有选择地只插入我想要的脚本.

所以我似乎必须script自己从响应文本中提取元素.基本上,我正在寻找正确的方法来做到这一点.这是我到目前为止所提出的:

function pullScripts(text) {
  var frag = document.createDocumentFragment()
    , div = document.createElement('div')
    , scriptElements
    ;

  // This is roughly how jQuery finds the scripts when cleaning text
  frag.appendChild(div);
  div.innerHTML = text;

  scriptElements = div.getElementsByClassName('class-for-scripts-that-we-want');

  $('head').append(scriptElements);
}
Run Code Online (Sandbox Code Playgroud)

虽然我还没有在任何糟糕的浏览器上测试过它,但效果还不错.无论如何,复制jQuery的这些基本功能只是为了避免其中一个功能(特殊script处理)感到不舒服.正如在小提琴中可以看到的那样,jQuery对象实际上确实包含scripts,但它不会返回类似.html()或者类似的东西.get().我错过了一些明显的做法吗?

注意:一旦jQuery的内部parseHTML函数暴露出来,这整个主题都没有实际意义

注2:我还阅读了尝试从jQuery ajax get响应中选择脚本标签,但是接受的答案是"你不能",然后是"使用正则表达式".两者都不令人满意

use*_*654 4

在 jQuery 1.8.0b1 中,您现在可以使用该$.parseHTML()方法来简化此操作。

$.parseHTML(xhr.responseText,true)将为您提供一个包含脚本元素的 jQuery 对象。然后,您可以提取脚本标签并在附加 html 后附加或执行它们。

$.ajax({
  url: '/whole_page.html',
  success: function (data, status, xhr) {
    var $result = $.parseHTML(xhr.responseText,true),
        $scripts = $result.find("script").add($result.filter("script")).detach();

    $('#menu').html($('#menu', $result).html());
    $('#content').html($('#content', $result).html());
    $('head').append($scripts);
  }
});
Run Code Online (Sandbox Code Playgroud)

您可能必须根据具体情况过滤脚本,以避免重复包含 jQuery。这将取决于您正在加载的内容。

如果升级 jQuery 不是一个选项,您只需实现 jQuery$.parseHTML并将其作为插件包含到当前的 jQuery 中

(function($) {
    if (!$.parseHTML) {
        var rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/;
        // data: string of html
        // context (optional): If specified, the fragment will be created in this context, defaults to document
        // scripts (optional): If true, will include scripts passed in the html string
        $.parseHTML = function( data, context, scripts ) {
            var parsed;
            if ( !data || typeof data !== "string" ) {
                return null;
            }
            if ( typeof context === "boolean" ) {
                scripts = context;
                context = 0;
            }
            context = context || document;

            // Single tag
            if ( (parsed = rsingleTag.exec( data )) ) {
                return [ context.createElement( parsed[1] ) ];
            }

            parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] );
            return jQuery.merge( [],
                (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes );
        }
    }
})(jQuery);
Run Code Online (Sandbox Code Playgroud)