You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

JS获取含表格内容的<template> innerHTML异常问题排查

问题原因分析

你遇到的问题其实是浏览器HTML解析器的自动修正行为导致的:

HTML规范里明确规定,<tbody>元素的直接子元素只能是<tr>(或相关表格行元素),而你写的{{ each(options.dossier.conteneurs) }}{{ /each }}属于纯文本节点,并不是合法的<tbody>子元素。浏览器在解析<template>内部的HTML结构时,会自动把这些“非法”的文本节点移到<table>元素外面,最终导致你看到的结构错乱。

解决方案

这里有几种可靠的解决方法,你可以根据自己的模板引擎选择合适的:

方法1:用注释包裹模板语法

把模板引擎的循环标签放在HTML注释里,这样浏览器解析时会忽略这些内容(不会当成非法节点移动),而你的模板引擎依然可以识别并解析注释内的语法:

<template id="fixedTemplate">
  <table class="table table-xs table-hover">
    <thead>
      <tr>
        <th>Conteneur</th>
      </tr>
    </thead>
    <tbody>
      <!-- {{ each(options.dossier.conteneurs) }} -->
      <tr>
        <td>{{ @this.numConteneur }}</td>
      </tr>
      <!-- {{ /each }} -->
    </tbody>
  </table>
</template>

大部分主流模板引擎(比如Handlebars、Underscore模板等)都支持解析注释内的模板语法,如果你用的引擎不支持,可以查看它的配置文档开启相关功能。

方法2:用<script>标签替代<template>

将模板内容放在<script>标签中,并指定一个非JavaScript的type属性(比如text/x-handlebars-template),这样浏览器不会解析里面的HTML结构,会完整保留你的原始模板内容:

<script id="fixedTemplate" type="text/x-handlebars-template">
  <table class="table table-xs table-hover">
    <thead>
      <tr>
        <th>Conteneur</th>
      </tr>
    </thead>
    <tbody>
      {{ each(options.dossier.conteneurs) }}
      <tr>
        <td>{{ @this.numConteneur }}</td>
      </tr>
      {{ /each }}
    </tbody>
  </table>
</script>

获取模板内容时,使用textContent而不是innerHTML

const templateContent = document.getElementById('fixedTemplate').textContent;

这种方法是最稳妥的,因为完全绕过了浏览器的HTML结构解析,确保模板内容100%保留原始格式。

方法3:使用模板引擎的原生语法兼容(如果支持)

有些模板引擎提供了专门的语法来避免HTML解析冲突,比如Handlebars的{{#each}}块级语法(注意和你用的each(...)写法的区别),不过这取决于你使用的具体引擎是否支持这种更贴合HTML结构的语法。

内容的提问来源于stack exchange,提问作者Ben Gubler

火山引擎 最新活动