获取所选元素的外部HTML


791

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

我四处搜寻,发现了几种非常“ hackish”类型的方法来克隆对象,将其添加到新创建的div等中,等等,但这看起来确实很脏。有没有更好的方法,还是新版本的jQuery(1.4.2)提供了某种outerHtml功能?


89
jQuery没有能力做这样的事情真是太离谱了。我也需要这个
约瑟夫·萨布(JosefSábl)2010年

9
我已经发布了功能请求,并对此线程进行了引用,最初的响应是肯定的。bugs.jquery.com/ticket/8142
mindplay.dk'2

11
为了节省一些人尝试Ulhas Tuscano解决方案的时间,该方法不起作用。
戴夫

73
呃,正在进行中。$('div')[0].outerHTML
Salman von Abbas 2012年

24
@Tuscan的意思是$(“#selectorid”)。prop(“ outerHTML”)
Guy Mograbi

Answers:


189

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

这个站点似乎为您提供了一个解决方案 :耶洛豆腐

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

4
我看到了这一点,但试图避免它,因为它似乎有点黑,并且本来应该有更好的方法,但是效果很好。谢谢。
瑞安(Ryan)2010年

359
$('[selector]')[0] .outerHTML
drogon 2012年

25
@drogon:请注意,outerHTMLFirefox仅从版本11(2012年3月)开始受支持。
布莱斯

8
@PavingWays:在Firefox中,防御:outerHTML是Microsoft发明的专有属性,而不是W3C标准。(有趣的事实:innerHTML仅从HTML5开始才标准化
Blaise 2012年

3
纯jsel.outerHTML || document.createElement('div').appendChild( el.cloneNode( true ) ).parentNode.innerHTML
rab

674

我认为目前(2012年5月1日),所有主流浏览器都支持externalHTML函数。在我看来,此片段就足够了。我个人会选择记住这一点:

// 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('');

编辑基本支持统计element.outerHTML


14
@SalmanPK FireFox直到2011-11-11才支持此属性。bugzilla.mozilla.org/show_bug.cgi?id=92264仍然有很多用户使用3.6。我认为这实际上是一个很好的例子,说明了为什么人们会选择使用jQuery而非本机功能。
路西法山姆

8
根据gs.statcounter.com,@ LuciferSam Firefox 3.6在全球市场份额约为6%。但是,将结果过滤到过去6个月(2012年12月11日至5月)以及美国,则将其从前12名中脱颖而出(以下3名) %)。我选择此窗口是因为本文建议FF 3.6的使用在2012年1月之后显着下降。鉴于此数据,我支持我的解决方案,以实现向后兼容的简单代码。
胡ric

4
完全同意。这是正确的答案,而不是其他人在暗示的东西。我选择的元素具有我要保留的属性,其他答案将丢失这些属性。地狱,这甚至可以在IE中使用!
马修·博尼格

不会。Firefox11直到2012年3月13日才发布(现已修复),即在撰写本文之前不到一年。jQuery的优点之一是它支持较旧的浏览器。我认为支持至少一年是合理的,并且某些站点显然会想要更多(记住,jQuery支持IE6)。
马修·弗莱申

7
@EricHu statcounter还指出IE8拥有9.3%的全球浏览器份额。但是我的一些网站接近40%的水平。这是相对的,每个网站的差异很大,Firefox 3.6在我的某些网站上仍然约占10%。全球市场份额一无所获。这全都与您的网站受众有关。
乔治·瑞斯

343

无需为其生成函数。像这样做:

$('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标签,因为它的键入次数更少并且工作原理相同。


82
我不知道为什么jQuery团队不添加externalHtml()方法?
Donny V.

1
@Derek,没关系。我正在使用DIV作为包装器,以便在其中添加一些东西。
Volomike 2012年

11
.clone()。wrap('<p>')。parent()。html(); 短
UGURGümüşhan

1
是的,减少了击键,并达到了相同的效果。
Volomike 2012年

14
最好使用DIV代替P作为一般解决方案-并非所有元素都可以作为有效HTML封装在P中。
开拓者

149

那又如何prop('outerHTML')呢?

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

并设置:

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

它为我工作。

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


4
与其他答案相比,代码非常简洁整洁。问:这是否具有与其他答案相同的externalHTML限制?它可以在FF <11下工作吗?
MacroMan 2014年

3
效果很好,这可能是这里最好的解决方案。就浏览器而言,这应该与outerHTLM兼容。prop()方法基本上只是获取外部HTML属性。
汤姆汤姆

2
此解决方案更好,但是Jquery 1.6.1于2011年发布。问题(和我的答复)来自2010
David V.

1
对我来说“ $('[selector]')[0] .outerHTML;” 在任何情况下均不起作用,但是“ $('#item-to-be-selected')。prop('outerHTML');” 是!
爱德华多·卢西奥

2
$('#item-to-be-selected')。attr('outerHTML'); // **对于早期的jQuery
Meetai.com 2015年

91

扩展jQuery:

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

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


8
此解决方案的小问题:您需要在wrap()之前先克隆(),否则将多余的包装<div>留在文档中。
mindplay.dk 2011年

1
谢谢,mindplay.dk-我编辑了代码,以纳入您的建议。:)
jessica

2
将其反转为: return $('<div>').append(this.clone()).html();这只是一点点。
贾斯汀·沃肯汀

2
您应该先检查externalHTML,然后将其用于支持它的浏览器
James Westgate

对于像我这样喜欢使用jQuery对象以及.appendTo()和.append()函数在AJAX响应中构建HTML的人来说,这非常有用。从我在测试中看到的结果来看,.outerHTML不适用于那些实例。其他人可能想进一步检查一下,但我没有时间。
肖恩·肯德尔

43

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

实际上,他的方法是一种更好的方法,因为您不使用克隆。如果您有子元素,则clone方法非常耗时,并且似乎没有其他人关心outerHTMLIE实际上具有该属性(是的,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;
    }
};

2
这对我来说非常有效。由于clone()and 的错误textarea,我需要一个非克隆解决方案,这是当下的事情。
Shpigford

5
+1以使用本机(outerHTML如果可用),因为Chrome除Internet Explorer之外还支持它。
Andy E

9
if(!('terHTML'in $ t [0]))alert('该死,更新您的浏览器');
psycho brm 2012年

19

要真正成为jQuery风格的人,您可能想要outerHTML()成为一个吸气者一个传授者,并使其行为尽可能相似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设置。

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


应该将其添加到jQuery核心中,以便人们无需考虑它。我唯一的问题是wrap()/ unwrap()的性能是否可能好于clone()?
IMSoP

1
IMSoP:通常,由于克隆必须复制所有子元素和元素的属性,因此包装/解开会更快。wrap()仅创建一个元素,而unwrap()则将其破坏,所有其他元素都将被移动,这在大多数情况下是相当快的操作。
Andy E

16

您也可以使用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">'

11

要将FULL jQuery插件制作为.outerHTML,请将以下脚本添加到任何js文件中,并在jQuery中的标头后添加:

更新新版本具有更好的控制以及更友好的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);

这样,您不仅可以获取一个元素的externalHTML,还可以一次获取多个元素的Array返回!并且可以在两种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();

片段示例:


9

你也可以这样

document.getElementById(id).outerHTML

id是您要查找的元素的id


4
$("#" + id).attr("id")是非常多余的。如果您已经在变量中包含id,为什么要使用jquery选择器从dom中拉出元素,然后查询其ID属性?
山姆·杜菲

7

我使用了Jessica的解决方案(由Josh编辑)来使externalHTML在Firefox上运行。但是问题是我的代码被破坏了,因为她的解决方案将元素包装到了DIV中。再添加一行代码即可解决该问题。

以下代码为您提供externalHTML,而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();

希望有人觉得它有用!


1
就像@mindplay在他的评论中建议的那样,只需使用.clone即可
Yarin


4

如果方案是动态追加新行,则可以使用以下命令:

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

.myrow是的类名<tr>。它会复制最后一行并将其作为新的最后一行插入。这也适用于IE7,而该[0].outerHTML方法不允许在ie7中进行分配


3

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

也就是说,您还可以遍历元素的属性以构造其HTML字符串表示形式。看来这就是如果要添加jQuery的任何externalHTML函数的实现方式。


3

我使用了杰西卡(Jessica)更新的Volomike解决方案。只是添加了一项检查以查看元素是否存在,并使其在不存在的情况下返回空白。

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

当然,可以像这样使用它:

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

3

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

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

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


2

请注意,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解决方案的另一个问题,请参阅上面的评论。


1
大多数jQuery“ getter”方法仅返回第一个元素的数据,因此匹配此行为会更有意义。
Andy E

我想我已经清楚说明了为什么会这样工作?当您有一个元素列表时,这将使丑陋/复杂的代码成为可能-如果出于某种原因,您只希望第一个元素的标记,只需在选择器中使用:first即可。
mindplay.dk 2011年

当然,就像您可以将map与其他所有人的解决方案一起使用以获取多个元素的HTML一样。我只是说要匹配标准jQuery方法的行为更加一致。
安迪E


2

我做了一个简单的测试,其中externalHTML是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");

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

outsideHTML
:81ms externalHTML2 :439ms

但是,如果我们使用不带本地externalHTML功能的tokimon解决方案(现在几乎所有浏览器都支持该功能)

我们得到

outsideHTML
:594ms externalHTML2 :332ms

现实世界中的示例中将会有更多的循环和元素,因此完美的组合将是

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

因此克隆方法实际上比包裹/解包裹方法快
(jQuery 1.7.2)


2

这是一个针对jquery进行了非常优化的externalHTML插件:(http://jsperf.com/outerhtml-vs-jquery-clone-hack/5 =>其他2个快速代码段与FF <11等某些浏览器不兼容。

(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 =>我不同意你的看法。outsideHMTL不需要getter和setter:jQuery已经给了我们'replaceWith'...

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

(对不起,没有足够的声誉写评论)


2

简短而甜美。

[].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, '')

2

使用香草JavaScript非常简单...

document.querySelector('#selector')

1

这对于更改dom上的元素非常有用,但不适用于将html字符串像这样传递到jquery中时:

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

经过一些操作后,我创建了一个函数,该函数可以使上述功能适用于html字符串:

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


0

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

我遇到了同样的问题,因为它返回的是innerHtml,因此缺少TR标签,该标签保留了该行的ID,这意味着无法重复该过程。

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

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

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


0

jQuery插件可以直接获取整个HTML元素:

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

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


-2
$("#myNode").parent(x).html(); 

如果要获取特定的节点,则其中的“ x”是节点号,第一个以0开头,应该得到所需的正确节点。如果您有子节点,那么您实际上应该在想要的ID上放一个ID,而在那个ID上只需输入零。使用这种方法,没有“ x”适合我。


1
人们对此表示反对,是否愿意发表评论?我将代码转到PARENT,然后获取内容的HTML,而不仅仅是.html()在给定元素上进行操作。这项工作,我想解释为什么不行。
vapcguy 2015年

-4

简单的解决方案。

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

-12
$("#myTable").parent().html();

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

那是你追求的吗?


25
绝对不,因为如果该父母还有其他孩子,他也会得到该html。
David V.

1
他说什么 我正在寻找元素本身,而不是元素及其所有父元素的其他孩子。这是怎么获得两票的呢???
瑞安
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.