16

我想从 DOM 中检索某个标签元素及其属性。例如,从

<a href="#" class="class">
  link text
</a>

我想得到<a href="#" class="class">,可选地用一个结束</a>,作为一个字符串或其他一些对象。在我看来,这类似于在.outerHTML没有.innerHTML.

最后,我需要它来通过 jQuery 包装一些其他元素。我试过

var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem);

.get()返回包含其内容的 DOM 元素。还

var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem.tagName).parent().attr(elem.attributes);

失败,因为elem.attributes返回 aNamedNodeMap不适用于 jQuery attr(),我无法转换它。承认上面的例子不是很有意义,因为它们也复制了元素的不再唯一的 ID。但是有什么简单的方法吗?非常感谢。

4

9 回答 9

18

对于未来的 Google 员工,有一种方法可以在没有 jQuery 的情况下做到这一点:

tag = elem.outerHTML.slice(0, elem.outerHTML.indexOf(elem.innerHTML));

由于outerHTMLcontains开始标记后跟包含内容的镜像innerHTML,我们可以将 outerHTML 从 0(开始标记的开头)到 innerHTML 开始的位置(开始标记的结尾)子串,并且由于 innerHTML 是 outerHTML 的镜像,除了对于开始标签,只留下开始标签!

这个适用于<br>标签、<meta>标签和其他空标签:

tag = elem.innerHTML ? elem.outerHTML.slice(0,elem.outerHTML.indexOf(elem.innerHTML)) : elem.outerHTML;

因为innerHTML 在自闭合标签中是空的,并且indexOf('')总是返回0,所以上面的修改会检查first.xml 的存在innerHTML

于 2016-01-06T17:26:09.930 回答
6
var wrapper = $('.class').clone().attr('id','').empty();
  • 您可能希望更改选择器以更精确地匹配<a>您要查找的元素。
  • clone()创建匹配元素的新副本,也可以选择复制事件处理程序。
  • 我曾经attr清除元素的 ID,这样我们就不会重复 ID。
  • empty()删除所有子节点(' innerHTML')。
于 2012-03-07T15:29:04.400 回答
3

这是我的解决方案:

opentag=elem.outerHTML.slice(0, elem.outerHTML.length-elem.innerHTML.length-elem.tagName.length-3);

我想,那个关闭标签的形式是:"</"+elem.tagName+">".

于 2018-10-09T11:50:55.673 回答
3

不幸的是,正如我在评论中所说, @AaronGillion 的回答并不可靠。谢谢@sus。我建议他/她的方式稍作改变来支持:<self-closing tags />

function getOpenTag(element: HTMLElement): string {
    const outerHtml = element.outerHTML;
    const len = outerHtml.length;
    
    const openTagLength = outerHtml[len - 2] === '/' ? // Is self-closing tag?
            len :
            len - element.innerHTML.length - (element.tagName.length + 3);
    // As @sus said, (element.tagName.length + 3) is the length of closing tag. It's always `</${tagName}>`. Correct?
    
    return outerHtml.slice(0, openTagLength);
}

代码在 TypeScript 中。如果需要 JavaScript,请删除类型 (HTMLElement和)。number

于 2019-04-26T02:19:36.440 回答
2

如果有人不使用 jQuery 。. .

elem.outerHTML
"<a href="#" class="class">
  link text
</a>"
elem.cloneNode().outerHTML
"<a href="#" class="class"></a>"

如果您希望 2014 年中之前发布的 Firefox 等安全,请使用 cloneNode(false) 以避免获取内部内容。

参考:https ://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode

于 2020-06-26T18:32:19.427 回答
1

这是我使用过的解决方案:

const wrap = document.createElement('div')
wrap.appendChild(target.cloneNode(true))
const openingTag = wrap.innerHTML.split('>')[0] + '>'
于 2019-08-15T15:11:12.850 回答
0

这可以在没有任何字符串操作的情况下完成。

相反,您可以使用元素的内部结构并从那里自己构建字符串:

function getTagHTML(el) {
  if (!el instanceof HTMLElement) return null;
  let result = `<${el.tagName.toLowerCase()}`;
  for (const attribute in el.attributes) {
    if (el.attributes[attribute].nodeValue) 
      result += ` ${el.attributes[attribute].name}="${el.attributes[attribute].nodeValue.replace(/"/g, "&quot;")}"`
  }
  result += `></${el.tagName.toLowerCase()}>`;
  return result;
}

console.log(getTagHTML(document.getElementById('outer')));
<div id="outer" class='i-want-"this"'>
  <span>I do not want this</span>
</div>

请注意,对于像<img />这样的自闭合元素,会给您一个不需要且不正确的闭合标签。随意调整代码。

于 2020-04-09T11:04:57.870 回答
0

+1 为上面的 cloneNode 答案

  • 创建没有内容的 HTML
  • 循环遍历属性
  • 可选的结束标签
  • 可选的自闭合标签

function getTagHTML(el, includeClosingTag=true , selfClosing = false) {
  //return el.cloneNode(false).outerHTML;
  if (el.attributes)
    return `<${el.localName}` + 
      [...el.attributes].map(
             attr => ` ${attr.name}="${attr.nodeValue.replace(/"/g, "&quot;")}"`
      ).join`` +
      `${selfClosing ? "/" : ""}>` + 
      (!selfClosing && includeClosingTag ? `</${el.localName}>` : "");
  else 
    return null;
}

document.body.querySelectorAll("*:not(script)").forEach(el=>{
  console.log(getTagHTML(el));
  console.log(getTagHTML(el,false));
  console.log(getTagHTML(el,false,true))
});
<div id="ONE" class='CLASSNAMES' attr1='"string"'>
   INNERHTML
  </div>
  <img id="TWO" src="https://svgshare.com/i/Uhq.svg"/>

于 2021-03-04T13:11:22.613 回答
0

我使用 Reg Exp 替换元素属性内所有可能的结束标签的解决方案:

const outerHTML = div.outerHTML;
const content = outerHTML.slice(0, outerHTML.length - div.innerHTML.length);
const dummy = content.replace(/'.*?'|".*?"/g, x => 'x'.repeat(x.length));
return content.slice(0, 1 + dummy.indexOf('>'));
于 2021-08-09T16:57:50.550 回答