【问题标题】:How to select elements from <template> with jQuery如何使用 jQuery 从 <template> 中选择元素
【发布时间】:2015-02-03 08:21:00
【问题描述】:

我有两个相似的选择。第一个使用&lt;div&gt; 标记,可以正常工作,第二个使用新的&lt;template&gt; 标记,它不再工作了。

谁能告诉我如何使用&lt;template&gt; 标记与jQuery 一起工作?

HTML

<div id="div">
    <div>content</div>
</div>

<template id="template">
    <div>content</div>
</template>

JavaScript

var $div = $('#div');
var $content = $div.find('div');
console.log($content); //works ($content.length == 1)

var $template = $('#template');
var $content = $template.find('div');
console.log($content); //doesn't work ($content.length == 0)

http://jsfiddle.net/s8b5w0Le/1/

【问题讨论】:

  • 我使用的是 Chrome 39.0.2171.71 m(以防万一)
  • $template[0].outerHTML 有效,所以理论上 jQuery 应该可以使用 &lt;template&gt; 标签
  • 所以,你不能单独使用jQuery来完成这项工作,但你可以检查content属性是否存在?如果是,请使用它 - 如果不是,常规的 jQuery 方式应该可以工作吗?

标签: javascript jquery html templates


【解决方案1】:

HTMLTemplateElement 将 DOM 保存到一个单独的属性中:

JQuery

<script src="jquery-3.1.0.js"></script>
<script type="text/javascript">
    $(document).ready(function()
    {
        var $div = $('#div');
        var $content = $div.find('div');
        console.log($content.text()); // output "content", inner div

        var $template = $('#template');
        var node = $template.prop('content');
        var $content = $(node).find('div');
        console.log($content.text()); // output "content", inner template
    });

JavaScript

document.createElement('template').content

【讨论】:

    【解决方案2】:

    我相当肯定这与 Chrome 对 shadow dom 的使用有关(感谢 Polymer...)

    您可以使用/deep/ 组合器来试试运气(可能不适用于其他浏览器),但我认为最可靠的解决方案是$template[0].outerHTML,如果您只需要文本,请在您的评论中使用。

    如果您需要 jQuery 功能,使用 $.parseXML(以避免 Chrome 的原生 dom 构造)可能会在所有浏览器中都可以解决问题(可以确认 Chrome + FF)。

    此处示例:http://jsfiddle.net/3fe9jjfj

    var tc = $('#template')[0].outerHTML;
    
    $template = $($.parseXML(tc)).contents();
    
    console.log($template);
    console.log($template.find('div'));
    

    两个日志都按我们的预期返回,$template 现在可以被视为一个普通的 jQuery 对象。

    【讨论】:

    • 太好了,谢谢!有时,最好的答案来自信誉评分最低的用户;)
    • 有一个问题,但是,如果你有非 XML 兼容的标签(即&lt;hr&gt;),你需要写&lt;hr/&gt;,但是outerHTML 仍然返回&lt;hr&gt; - 所以这个可能很棘手
    • @SimonFerndriger 根据您对模板的使用要求,您可以选择使用自定义标签名称(例如xtemplate)而不是template。如果您使用模板将数据与 Handlebars 或其他东西绑定,那么应该可以。再次,hacky,但我想这是早期采用的预期
    【解决方案3】:

    正如其他人所指出的,Chrome 将 &lt;template&gt; 子元素放入影子 DOM。要访问它们:

    // Access the JavaScript object for the template content
    $('template')[0]
    
    // Make a jQuery selection out of it
    $($('template')[0])
    
    // Now you can search it
    $($('template')[0]).find('div.someclass').css('color','#000');
    

    【讨论】:

      【解决方案4】:

      如果模板元素内的元素用容器包装,则可以照常使用所有 JQuery 方法。

      const temp = $("#template").contents().clone();
      $(temp).find("h1").text("A dynamic title");
      temp.appendTo($("#app"));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      
      <div id="app"></div>
      
      <template id="template">
          <div class="container">
              <h1>lorem ipsum</h1>
              <p>lorem ipsum </p>
              <img src="" alt="">
          </div>
      </template>

      也可以使用 JQuery 动态附加容器。或者,如果您不需要容器,则可以附加其内容。

      const temp = $('<div></div>').html($("#template").contents().clone());
      $(temp).find("h1").text('dynamic title');
      $(temp).find("p").text('But no container this time');
      temp.contents().appendTo($("#app"));
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      
      <div id="app"></div>
      
      <template id="template">
          <h1>lorem ipsum</h1>
          <p>lorem ipsum </p>
          <img src="" alt="">
      </template>

      【讨论】:

        【解决方案5】:
        <template>
           <div class="template-container">
              <div class="content">content</div>
           </div>
        </template>
        
        var templateHtml = ('#template').html() // this will return the template container div
        var template = $(templateHtml);
        var content = template.find('.content');
        
        console.log(content);
        

        【讨论】:

        • 请在您的代码中添加一些解释。
        • 这只会使用模板代码创建一个新元素。它不选择实际的模板内容本身。它本质上是一个副本。这对于在模板元素中操作 DOM 之类的事情没有帮助。
        【解决方案6】:

        一种方式,派对为时已晚,但我最终这样做了:

        function resolveTemplate(id) {
          return $(id).contents();
        }
        
        ...
        
        var $searchIcon = resolveTemplate('#search-icon-template');
        $('#div').append($searchIcon);
        

        【讨论】:

          【解决方案7】:

          var $content = $template.content.find('div');

          ...而不是...

          var $content = $template.find('div');

          为我工作。

          【讨论】:

          • 好的,那么 Internet Explorer 呢?
          • 您可能是指$template[0].content(来自 HTMLObject,而不是来自 jQuery 对象)——但据我所知,这在 Internet Explorer 中不起作用:developer.mozilla.org/en-US/docs/Web/HTML/Element/template
          • 我做了 console.log($template) 来查看模板标签的结构。在 Chrome 和 Firefox 中,它似乎有所不同。
          【解决方案8】:

          HTML5 模板默认为display: none;,模板中的childNodes 无效,如果你在控制台中检查它会发现不同的东西

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-02-03
            • 1970-01-01
            • 2019-05-21
            • 2011-11-19
            • 2012-04-12
            • 2012-05-17
            • 1970-01-01
            相关资源
            最近更新 更多