获取选定元素的外部 HTML

Posted

技术标签:

【中文标题】获取选定元素的外部 HTML【英文标题】:Get selected element's outer HTML 【发布时间】:2011-01-26 01:25:28 【问题描述】:

我正在尝试使用 jQuery 获取选定对象的 html。我知道.html() 函数;问题是我需要包含所选对象的 HTML(在这种情况下为表格行,.html() 仅返回行内的单元格)。

我四处搜索,发现了一些非常“hackish”类型的克隆对象的方法,将其添加到新创建的 div 等等,但这似乎真的很脏。有没有更好的方法,或者新版本的 jQuery (1.4.2) 提供了任何outerHtml 功能?

【问题讨论】:

jQuery 没有办法做这样的事情真是离谱。我也需要这个。 我发布了一个功能请求,并引用了这个线程,最初的反应是肯定的。 bugs.jquery.com/ticket/8142 为了节省一些人尝试 Ulhas Tuscano 解决方案的几秒钟时间,它不起作用。 呃,事情还在继续。 $('div')[0].outerHTML. @Tuscan 的意思是 $("#selectorid").prop("outerHTML") 【参考方案1】:

相信目前(5/1/2012),所有主流浏览器都支持outerHTML功能。在我看来,这个 sn-p 就足够了。我个人会选择记住这一点:

// Gives you the DOM element without the outside wrapper you want
$('.classSelector').html()

// Gives you the outside wrapper as well only for the first element
$('.classSelector')[0].outerHTML

// Gives you the outer HTML for all the selected elements
var html = '';
$('.classSelector').each(function () 
    html += this.outerHTML;
);

//Or if you need a one liner for the previous code
$('.classSelector').get().map(function(v)return v.outerHTML).join('');

编辑:Basic support stats 代表element.outerHTML

火狐(壁虎):11 ....Released 2012-03-13 铬:0.2 ....Released 2008-09-02 Internet Explorer 4.0...Released 1997 歌剧 7 ....................Released 2003-01-28 Safari 1.3 ....................Released 2006-01-12

【讨论】:

@SalmanPK FireFox 直到 2011 年 11 月 11 日才支持此属性。 bugzilla.mozilla.org/show_bug.cgi?id=92264 还是有很多用户卡在 3.6 上。我认为这实际上是一个完美的例子,说明为什么人们会选择使用 jQuery 而不是原生功能。 @LuciferSam Firefox 3.6 根据 gs.statcounter.com 的全球市场份额约为 6% 但是,filtering the results 在过去 6 个月(2012 年 12 月 11 日至 2012 年 5 月)和美国推动它前 12 名(低于 3%)。我之所以选择这个窗口,是因为this article 表明 FF 3.6 的使用率在 2012 年 1 月之后显着下降。鉴于这些数据,我支持我的解决方案,以实现更简单的代码而不是向后兼容性。 不能再同意了。这是正确的答案,而不是人们建议的其他内容。我选择的元素具有我想要保留的属性,这些属性会被其他答案丢失。见鬼,这甚至可以在 IE 中使用! 没有。 Firefox 11 直到 2012 年 3 月 13 日 (现已修复)才发布,即在撰写本文时不到一年前。 jQuery 的好处之一是它支持较旧的浏览器。我认为至少支持一年是合理的,有些网站显然会想要更多(记住,jQuery 支持 IE6)。 @EricHu statcounter 还指出 IE8 拥有 9.3% 的全球浏览器份额。然而,我的一些网站接近 40% 的标记。这都是相对的,并且因网站而异,Firefox 3.6 在我的一些网站上仍然占大约 10%。全球市场份额毫无意义。这完全取决于您的网站受众。【参考方案2】:

无需为它生成函数。就这样做吧:

$('a').each(function()
    var s = $(this).clone().wrap('<p>').parent().html();
    console.log(s);
);

(顺便说一下,您的浏览器控制台会显示记录的内容。自 2009 年左右以来的大多数最新浏览器都具有此功能。)

最后的魔力是这样的:

.clone().wrap('<p>').parent().html();

克隆意味着您实际上并没有干扰 DOM。在没有它的情况下运行它,您会看到在所有超链接之前/之后插入p 标记(在本例中),这是不可取的。所以,是的,使用.clone()

它的工作方式是获取每个a标签,在RAM中对其进行克隆,用p标签包装,获取它的父级(即p标签),然后获取innerHTML 它的属性。

编辑:听取建议并将div 标记更改为p 标记,因为它的输入更少且工作方式相同。

【讨论】:

不知道为什么jQuery团队不添加outerHtml()方法? @Derek,没关系。我使用 DIV 作为包装器,以便在其中获取一些东西。 .clone().wrap('

').parent().html();更短

可以,按键次数少,效果一样。 最好使用 DIV 而不是 P 作为通用解决方案 - 并非所有元素都可以作为有效 HTML 包装在 P 中。【参考方案3】:

2014 年编辑:问题和此回复来自 2010 年。当时,没有更好的解决方案被广泛使用。现在,许多其他回复更好:例如 Eric Hu 或 Re Capcha。

这个网站似乎有适合你的解决方案: jQuery: outerHTML | Yelotofu

jQuery.fn.outerHTML = function(s) 
    return s
        ? this.before(s).remove()
        : jQuery("<p>").append(this.eq(0).clone()).html();
;

【讨论】:

我看到了这一点,但试图避免它,因为它似乎很骇人听闻,而且应该有更好的方法,但它运作良好。谢谢。 $('[selector]')[0].outerHTML @drogon:请注意,Firefox 仅从版本 11(2012 年 3 月)开始支持 outerHTML @PavingWays:为 Firefox 辩护:outerHTML 是微软发明的专有属性,而不是 W3C 标准。 (有趣的事实:innerHTML is standardized only since HTML5) 纯js el.outerHTML || document.createElement('div').appendChild( el.cloneNode( true ) ).parentNode.innerHTML【参考方案4】:

怎么样:prop('outerHTML')

var outerHTML_text = $('#item-to-be-selected').prop('outerHTML');

设置:

$('#item-to-be-selected').prop('outerHTML', outerHTML_text);

它对我有用。

PS:这是在jQuery 1.6中添加的。

【讨论】:

与其他答案相比,代码非常简洁。问:这是否具有与其他答案中提到的相同的 outerHTML 限制?它适用于 FF 效果很好,这可能是这里最好的解决方案。就浏览器而言,这应该与 outerHTLM 一样兼容。 prop() 方法基本上只是获取 outerHTML 属性。 此解决方案更好,但是 Jquery 1.6.1 于 2011 年发布。问题(和我的回复)来自 2010 年。 对我来说 "$('[selector]')[0].outerHTML;"在任何情况下都不起作用,但是 "$('#item-to-be-selected').prop('outerHTML');"是的! $('#item-to-be-selected').attr('outerHTML'); //** 对于早期的 jQuery 的【参考方案5】:

扩展 jQuery:

(function($) 
  $.fn.outerHTML = function() 
    return $(this).clone().wrap('<div></div>').parent().html();
  ;
)(jQuery);

并像这样使用它:$("#myTableRow").outerHTML();

【讨论】:

此解决方案的小问题:您需要在 wrap() 之前 clone(),否则您将在文档中留下额外的包装 。 谢谢,mindplay.dk -- 我编辑了代码以纳入您的建议......很好。 :) 如何将其反转为:return $('&lt;div&gt;').append(this.clone()).html(); 这只是更中肯的一点。 您应该先检查outerHTML,然后将其用于支持它的浏览器 这对于像我这样喜欢使用 jQuery 对象以及 .appendTo() 和 .append() 函数在 AJAX 响应中构建 HTML 的人来说非常棒。 .outerHTML 不适用于我在测试中看到的那些实例。其他人可能想进一步检查一下,但我没有时间。【参考方案6】:

我同意 Arpan(2010 年 12 月 13 日 5:59)。

他的做法实际上是一种更好的做法,因为你不使用克隆。如果您有子元素,则克隆方法非常耗时,而且似乎没有其他人关心 IE 实际上有 outerHTML 属性(是的,IE 实际上有一些有用的技巧)。

但我可能会创建他的脚本有点不同:

$.fn.outerHTML = function() 
    var $t = $(this);
    if ($t[0].outerHTML !== undefined) 
        return $t[0].outerHTML;
     else 
        var content = $t.wrap('<div/>').parent().html();
        $t.unwrap();
        return content;
    
;

【讨论】:

这对我来说非常有效。由于 clone()textarea 的错误,我需要一个非克隆解决方案,这是正确的。 +1 用于在可用的情况下使用本机 outerHTML,因为除了 Internet Explorer 之外,Chrome 也支持它。 if (!('outerHTML' in $t[0])) alert('god dammit, update your browser');【参考方案7】:

要成为真正的 jQuery 风格,您可能希望 outerHTML() 成为 getter setter,并使其行为尽可能类似于 html()

$.fn.outerHTML = function (arg) 
    var ret;

    // If no items in the collection, return
    if (!this.length)
        return typeof arg == "undefined" ? this : null;
    // Getter overload (no argument passed)
    if (!arg) 
        return this[0].outerHTML || 
            (ret = this.wrap('<div>').parent().html(), this.unwrap(), ret);
    
    // Setter overload
    $.each(this, function (i, el) 
        var fnRet, 
            pass = el,
            inOrOut = el.outerHTML ? "outerHTML" : "innerHTML";

        if (!el.outerHTML)
            el = $(el).wrap('<div>').parent()[0];

        if (jQuery.isFunction(arg))  
            if ((fnRet = arg.call(pass, i, el[inOrOut])) !== false)
                el[inOrOut] = fnRet;
        
        else
            el[inOrOut] = arg;

        if (!el.outerHTML)
            $(el).children().unwrap();
    );

    return this;

工作演示:http://jsfiddle.net/AndyE/WLKAa/

这允许我们将参数传递给outerHTML,可以是

一个可取消的函数 — function (index, oldOuterHTML) — 返回值将成为元素的新 HTML(除非返回 false)。 一个字符串,它将代替每个元素的 HTML。

有关更多信息,请参阅html() 的 jQuery 文档。

【讨论】:

这应该被添加到jQuery核心中,这样人们就不需要考虑它了。我唯一的问题是 wrap()/unwrap() 的性能是否可能比 clone() 更好或更差? IMSoP:通常,wrap/unwrap 会更快,因为 clone 必须复制元素的所有子元素和属性。 wrap() 只创建一个元素,而 unwrap() 销毁它,所有其他元素都只是移动,大多数时候这是一个相当快的操作。【参考方案8】:

也可以使用get(获取jQuery对象匹配的DOM元素)。

例如:

$('div').get(0).outerHTML;//return "<div></div>"

作为扩展方法:

jQuery.fn.outerHTML = function () 
  return this.get().map(function (v) 
    return v.outerHTML
  ).join()
;

或者

jQuery.fn.outerHTML = function () 
  return $.map(this.get(), function (v) 
    return v.outerHTML
  ).join()
;

多选,返回所有匹配元素的外层html。

$('input').outerHTML()

返回:

'<input id="input1" type="text"><input id="input2" type="text">'

【讨论】:

【参考方案9】:

要将完整的 jQuery 插件设置为 .outerHTML,请将以下脚本添加到任何 js 文件中,并在标头中包含 jQuery 之后:

update 新版本有更好的控制以及对 jQuery Selector 更友好的服务! :)

;(function($) 
    $.extend(
        outerHTML: function() 
            var $ele = arguments[0],
                args = Array.prototype.slice.call(arguments, 1)
            if ($ele && !($ele instanceof jQuery) && (typeof $ele == 'string' || $ele instanceof HTMLCollection || $ele instanceof Array)) $ele = $($ele);
            if ($ele.length) 
                if ($ele.length == 1) return $ele[0].outerHTML;
                else return $.map($("div"), function(ele,i)  return ele.outerHTML; );
            
            throw new Error("Invalid Selector");
        
    )
    $.fn.extend(
        outerHTML: function() 
            var args = [this];
            if (arguments.length) for (x in arguments) args.push(arguments[x]);
            return $.outerHTML.apply($, args);
        
    );
)(jQuery);

这将使您不仅可以获取一个元素的外层HTML,还可以一次获取多个元素的数组返回!并且可以在这两种 jQuery 标准样式中使用:

$.outerHTML($("#eleID")); // will return outerHTML of that element and is 
// same as
$("#eleID").outerHTML();
// or
$.outerHTML("#eleID");
// or
$.outerHTML(document.getElementById("eleID"));

对于多个元素

$("#firstEle, .someElesByClassname, tag").outerHTML();

片段示例:

console.log('$.outerHTML($("#eleID"))'+"\t", $.outerHTML($("#eleID"))); 
console.log('$("#eleID").outerHTML()'+"\t\t", $("#eleID").outerHTML());
console.log('$("#firstEle, .someElesByClassname, tag").outerHTML()'+"\t", $("#firstEle, .someElesByClassname, tag").outerHTML());

var checkThisOut = $("div").outerHTML();
console.log('var checkThisOut = $("div").outerHTML();'+"\t\t", checkThisOut);
$.each(checkThisOut, function(i, str) $("div").eq(i).text("My outerHTML Was: " + str); );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://rawgit.com/JDMcKinstry/ce699e82c7e07d02bae82e642fb4275f/raw/deabd0663adf0d12f389ddc03786468af4033ad2/jQuery.outerHTML.js"></script>
<div id="eleID">This will</div>
<div id="firstEle">be Replaced</div>
<div class="someElesByClassname">At RunTime</div>
<h3><tag>Open Console to see results</tag></h3>

【讨论】:

【参考方案10】:

你也可以这样做

document.getElementById(id).outerHTML

其中 id 是您要查找的元素的 id

【讨论】:

$("#" + id).attr("id") 非常多余。如果变量中已经有 id,为什么要使用 jquery 选择器从 dom 中提取元素,然后查询其 ID 属性?【参考方案11】:

我使用 Jessica 的解决方案(由 Josh 编辑)让 outerHTML 在 Firefox 上运行。然而问题是我的代码被破坏了,因为她的解决方案将元素包装到了一个 DIV 中。再添加一行代码就解决了这个问题。

以下代码为您提供外层HTML,保持 DOM 树不变。

$jq.fn.outerHTML = function() 
    if ($jq(this).attr('outerHTML'))
        return $jq(this).attr('outerHTML');
    else
    
    var content = $jq(this).wrap('<div></div>').parent().html();
        $jq(this).unwrap();
        return content;
    

并像这样使用它:$("#myDiv").outerHTML();

希望有人觉得它有用!

【讨论】:

只需使用 .clone 就像 @mindplay 在他的评论中建议的那样 - 它更容易【参考方案12】:
// no cloning necessary    
var x = $('#xxx').wrapAll('<div></div>').parent().html(); 
alert(x);

在这里提琴:http://jsfiddle.net/ezmilhouse/Mv76a/

【讨论】:

【参考方案13】:

如果场景是动态追加新行,你可以使用这个:

var row = $(".myRow").last().clone();
$(".myRow").last().after(row);

.myrow&lt;tr&gt; 的类名。它复制最后一行并将其作为新的最后一行插入。 这也适用于 IE7,而 [0].outerHTML 方法不允许在 ie7

中分配

【讨论】:

【参考方案14】:

node.cloneNode() 看起来不像是 hack。您可以克隆节点并将其附加到任何所需的父元素,还可以通过操作单个属性来操作它,而不必例如在其上运行正则表达式,或者将其添加到 DOM 中,然后对其进行操作。

也就是说,您也可以iterate over the attributes of the element 构造它的 HTML 字符串表示形式。如果 jQuery 添加一个,这似乎就是任何 outerHTML 函数的实现方式。

【讨论】:

【参考方案15】:

我使用了由 Jessica 更新的 Volomike 解决方案。只是添加了一个检查以查看元素是否存在,并使其返回空白以防万一。

jQuery.fn.outerHTML = function() 
return $(this).length > 0 ? $(this).clone().wrap('<div />').parent().html() : '';
;

当然,像这样使用它:

$('table#buttons').outerHTML();

【讨论】:

【参考方案16】:

你可以在这里找到一个好的 .outerHTML() 选项https://github.com/darlesson/jquery-outerhtml。

与仅返回元素的 HTML 内容的 .html() 不同,此版本的 .outerHTML() 返回所选元素及其 HTML 内容或将其替换为 .replaceWith() 方法,但不同之处在于允许替换 HTML被链接继承。

示例也可以在上面的 URL 中看到。

【讨论】:

【参考方案17】:

使用原生 javascript 非常简单...

document.querySelector('#selector')

【讨论】:

【参考方案18】:

请注意,Josh 的解决方案仅适用于单个元素。

可以说,“外部”HTML 只有在您只有一个元素时才真正有意义,但在某些情况下,获取 HTML 元素列表并将它们转换为标记是有意义的。

扩展 Josh 的解决方案,这个将处理多个元素:

(function($) 
  $.fn.outerHTML = function() 
    var $this = $(this);
    if ($this.length>1)
      return $.map($this, function(el) return $(el).outerHTML(); ).join('');
    return $this.clone().wrap('<div/>').parent().html();
  
)(jQuery);

编辑:修复了 Josh 解决方案的另一个问题,请参阅上面的评论。

【讨论】:

大多数 jQuery "getter" 方法只返回第一个元素的数据,所以匹配这种行为会更有意义。 我想我已经清楚地说明了为什么它会这样工作?当你有一个元素列表时,它会产生丑陋/复杂的代码 - 如果由于某种原因你只想要第一个元素的标记,只需在选择器中使用 :first 。 当然,就像您可以将 map 与其他人的解决方案一起使用来获取多个元素的 HTML。我只是说匹配标准 jQuery 方法的行为更加一致。【参考方案19】:

Anothe similar solution 添加了临时 DOM 对象的 remove()

【讨论】:

【参考方案20】:

我做了这个简单的测试,outerHTML 是 tokimon 解决方案(没有克隆),outerHTML2 是 jessica 解决方案(克隆)

console.time("outerHTML");
for(i=0;i<1000;i++)
                  
  var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML();
                  
console.timeEnd("outerHTML");

console.time("outerHTML2");

 for(i=0;i<1000;i++)
                  
   var html = $("<span style='padding:50px; margin:50px; display:block'><input type='text' title='test' /></span>").outerHTML2();
                   
  console.timeEnd("outerHTML2");

我的 chromium(版本 20.0.1132.57 (0))浏览器中的结果是

外部HTML:81 毫秒 外层HTML2:439ms

但是如果我们使用没有原生 outerHTML 功能的 tokimon 解决方案(现在几乎每个浏览器都支持该功能)

我们得到

外部HTML:594 毫秒 外层HTML2:332ms

在现实世界的例子中会有更多的循环和元素,所以完美的组合应该是

$.fn.outerHTML = function() 

  $t = $(this);
  if( "outerHTML" in $t[0] ) return $t[0].outerHTML; 
  else return $t.clone().wrap('<p>').parent().html(); 

所以 clone 方法实际上比 wrap/unwrap 方法快 (jquery 1.7.2)

【讨论】:

【参考方案21】:

这是一个非常优化的 jquery outerHTML 插件: (http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 => 其他 2 个快速代码 sn-ps 与 FF

(function($) 

  var DIV = document.createElement("div"),
      outerHTML;

  if ('outerHTML' in DIV) 
    outerHTML = function(node) 
      return node.outerHTML;
    ;
   else 
    outerHTML = function(node) 
      var div = DIV.cloneNode();
      div.appendChild(node.cloneNode(true));
      return div.innerHTML;
    ;
  

  $.fn.outerHTML = function() 
    return this.length ? outerHTML(this[0]) : void(0);
  ;

)(jQuery);

@Andy E => 我不同意你的看法。 outerHMTL 不需要 getter 和 setter:jQuery 已经给了我们 'replaceWith'...

@mindplay => 你为什么要加入所有的outerHTML? jquery.html 仅返回 FIRST 元素的 HTML 内容。

(对不起,没有足够的声望写cmets)

【讨论】:

【参考方案22】:

又短又甜。

[].reduce($('.x'), function(i,v) return i+v.outerHTML, '')

或借助箭头功能使事件更甜蜜

[].reduce.call($('.x'), (i,v) => i+v.outerHTML, '')

或者根本没有 jQuery

[].reduce.call(document.querySelectorAll('.x'), (i,v) => i+v.outerHTML, '')

或者如果您不喜欢这种方法,请检查

$('.x').get().reduce((i,v) => i+v.outerHTML, '')

【讨论】:

【参考方案23】:

这对于更改 dom 上的元素非常有用,但不适用于将 html 字符串传入 jquery 时,如下所示:

$('<div id="foo">Some <span id="blog">content</span></div>').find('#blog').outerHTML();

经过一些操作,我创建了一个函数,它允许上面的内容在 ie 中用于 html 字符串:

$.fn.htmlStringOuterHTML = function()      
    this.parent().find(this).wrap('<div/>');        
    return this.parent().html();
;

【讨论】:

【参考方案24】:

$.html = el =&gt; $("&lt;div&gt;"+el+"&lt;/div&gt;").html().trim();

【讨论】:

【参考方案25】:

我在寻找问题的答案时遇到了这个问题,即我试图删除表格行,然后将其重新添加到表格底部(因为我正在动态创建数据行但想显示底部的“添加新记录”类型行)。

我遇到了同样的问题,因为它返回的是 innerHtml,所以缺少 TR 标签,该标签保存了该行的 ID,这意味着不可能重复该过程。

我找到的答案是 jquery remove() 函数实际上将元素作为对象返回,它会删除它。因此,要删除并重新添加一行,就这么简单...

var a = $("#trRowToRemove").remove();            
$('#tblMyTable').append(a);  

如果您不是要删除对象而是想将其复制到其他地方,请改用clone() 函数。

【讨论】:

【参考方案26】:

jQuery插件作为简写直接获取整个元素HTML:

jQuery.fn.outerHTML = function () 
    return jQuery('<div />').append(this.eq(0).clone()).html();
;

并像这样使用它:$(".element").outerHTML();

【讨论】:

【参考方案27】:

纯 JavaScript:

var outerHTML = function(node) 
  var div = document.createElement("div");
  div.appendChild(node.cloneNode(true));
  return div.innerHTML;
;

【讨论】:

【参考方案28】:
$("#myNode").parent(x).html(); 

其中“x”是节点编号,从 0 开始作为第一个,如果您想获得特定的节点,应该会获得您想要的正确节点。如果你有子节点,你真的应该在你想要的那个上放一个 ID,不过,在那个上只是零。使用这种方法并且没有“x”对我来说效果很好。

【讨论】:

人们对此投了反对票,想发表评论吗?我将代码上传到 PARENT,然后获取内容的 HTML——不仅仅是在给定元素上执行 .html()。这行得通,我想解释一下为什么行不通。【参考方案29】:

简单的解决方案。

var myself = $('#div').children().parent();

【讨论】:

【参考方案30】:
$("#myTable").parent().html();

也许我没有正确理解您的问题,但这将获得所选元素的父元素的 html。

这就是你所追求的吗?

【讨论】:

实际上没有,因为如果那个父母有其他孩子,他也会得到那个 html。 ...他说的。我正在寻找元素本身,而不是它及其所有父母的其他孩子。这是怎么得到两票的???

以上是关于获取选定元素的外部 HTML的主要内容,如果未能解决你的问题,请参考以下文章

如何在jquery中获取当前选定元素的标记名[重复]

获取除不可选择元素之外的选定文本

document.querySelectorAll 一次获取所有选定元素的 innerText 纯javascript

如何使用 jquery 遍历 HTML 页面的所有选定元素

Cheerio 获取元素外部 html

从选择元素中获取选定的选项