【问题标题】:How to transclude HTML elements in a document如何在文档中嵌入 HTML 元素
【发布时间】:2013-03-13 01:23:50
【问题描述】:

是否可以像在 MediaWiki 中那样将一个 HTML 元素转换为文档的多个位置?我想在其他元素中包含元素,而不复制和粘贴它们的内容。我知道可以使用 iframe 将网页嵌入到其他网页中,但是是否有任何可靠的方法可以将 HTML 元素嵌入到同一页面上的其他 HTML 元素中?

<p id = "p1">This is paragraph 1. </p>
<p id = "p2">
    This is paragraph 2.
    </p>
<p id = "p3">This is paragraph 3. It should contain paragraphs 1 and 2.
    <!-- {{p1}} {{p2}} -->
</p>

【问题讨论】:

  • 您可能需要为此使用 JavaScript。
  • @Tyriar 我在这个问题中添加了 JavaScript 标签。感谢您指出了这一点。 :)
  • 假设这段代码有效,重复段落的id 属性会发生什么?它们不应该保持不变......应该将它们删除或更改吗?
  • @GGG 他们应该被删除,而不是被保留在那里。 (也许使用class 属性而不是id 属性会更好,这样就不需要删除任何内容。)
  • @AndersonGreen,听起来很合理。你喜欢用这样的 HTML 注释写它,还是像 &lt;script&gt;transclude("p1")&lt;/script&gt; 这样的东西适合你?

标签: javascript html transclusion


【解决方案1】:

这有点小技巧,但它适用于 Firefox、Chrome 和 Opera。没有在 IE 中测试,这台笔记本电脑上没有它...如果你有机会测试,请告诉我它是否在 IE 中工作。

把它放在文档的headscript 标记中:

function transclude(elementId) {
    var clone = document.getElementById(elementId).cloneNode(true),
        placeholder;
    clone.id = null;
    document.write('<br id="__placeholder__">');
    placeholder = document.getElementById('__placeholder__');
    placeholder.parentNode.insertBefore(clone, placeholder);
    placeholder.parentNode.removeChild(placeholder);
    return transclude;
}

要转换元素,请使用:

<p id="p1">This is paragraph 1. </p>
<p id="p2">
    This is paragraph 2.
</p>
<p id="p3">This is paragraph 3. It should contain paragraphs 1 and 2.
    <script>transclude("p1")("p2")</script>
</p>

注意事项:

  • ID 属性已从克隆元素中移除。

  • 只要包含对transclude 的调用的脚本运行,元素就会被嵌入,无需等待文档加载。由于使用了document.write,所以在文档加载完成后这将不起作用。

  • 我们使用一个虚拟占位符元素 &lt;br&gt; 来防止 document.write 的副作用,例如在已打开但未终止的 &lt;p&gt; 之后写入 &lt;p&gt; 会导致第一个标签提前终止。

    换句话说,占位符元素的标签名称应该不同于任何未终止的外部标签的名称,因此是自终止的&lt;br&gt;标签。

  • Transclusion 函数返回自身以进行链接。

http://jsfiddle.net/bcWjE/1

【讨论】:

  • 请注意,这在 2013 年是一个合理的答案,但在 2020 年(及以后)你不应该使用document.write。在这种情况下,您将使用一些通过 &lt;script src="transclude.js" async defer&gt; 加载的 JS(async 独立加载它,defer 在解析 DOM 后但在控制权交给用户之前执行它)嵌入标记(例如任何 {{ ... }}{% transclude ... %} 或其他东西)并深度克隆具有匹配 id 属性的节点。
  • @Mike'Pomax'Kamermans 使用async defer的原因是为了让页面加载更快。避免使用document.write 的原因是因为它可以在编写部分标记时导致重新解析(并且它还支撑页面,等待JavaScript 运行)。这段代码没有这些问题。事实上,由于异步网络请求,您的解决方案会导致布局跳动,内容发生变化。如果您愿意,请避免使用 document.write,但 async defer 在此处肯定不正确。 (我什至认为,暂停页面是正确的行为。)
  • 现在是 2022 年:优雅地加载它们,或者在服务器端生成您的内容,这样您甚至不需要 JS 来嵌入内容。多年来一直保持页面不正确。
【解决方案2】:

使用 jQuery:

$(document).ready(function(){
  $('#p3').html($('#p1').html()+$('#p2').html())
});

JsFiddle

【讨论】:

  • 这将创建两个具有相同id 属性的元素。我也不相信 OP 在任何地方都提到了 jQuery。
【解决方案3】:

使用jQuery's .clone() method 可能更合适,它执行 DOM 节点的深层复制,保留绑定方法之类的东西。

$('.hello').clone().appendTo('.goodbye'); 应用于

的简单示例(来自文档)
<div class="container">
  <div class="hello">Hello</div>
  <div class="goodbye">Goodbye</div>
</div>

结果

<div class="container">
  <div class="hello">Hello</div>
  <div class="goodbye">
    Goodbye
    <div class="hello">Hello</div>
  </div>
</div>

【讨论】:

  • 我可以接受反对票,但添加评论:反对票不评论对回答者或 OP 没有任何用处。
猜你喜欢
  • 1970-01-01
  • 2021-09-07
  • 2012-06-16
  • 1970-01-01
  • 2018-08-03
  • 2011-03-10
  • 1970-01-01
  • 1970-01-01
  • 2012-02-21
相关资源
最近更新 更多